R: lijst met ingesloten identifiers omzetten in dataframe

Ik ben helemaal nieuw voor R en heb veel geleerd van het bekijken van andere vragen hier op deze mooie website!

maar nu heb ik te maken met een probleem met gegevensbeheer dat ik uit andere voorbeelden niet kan achterhalen, dus ik hoop dat u kunt helpen.

Ik heb een reeks enquêtereacties die ik heb gelezen in een csv-bestand en samengevouwen in een vector zoals in het volgende voorbeeld:

test <- c(
  "[1234],Bob Smith,",
  "Q-0,Male",
  "Q-1,18-25",
  "Q-2,Computer Science",
  ",",
  "[5678],Julie Lewis",
  "Q-0,Female",
  "Q-1,18-25",
  ",",
  ","
)

Merk op dat "," op een eigen regel verschijnt omdat ik fill = TRUE heb gebruikt in read.csv om het hoofd te bieden aan het feit dat niet alle de lijnen waren even lang. Merk ook op dat niet alle vragen zijn beantwoord door alle respondenten.

Ik moet dit in een dataframe van de volgende structuur veranderen:

     ID      name         gender   age    major
1    [1234]  Bob Smith    Male     18-25  Computer Science
2    [5678]  Julie Lewis  Female   18-25  NA
   ...

Het lijkt erop dat ik de vector niet per rij in een matrix of dataframe kan lezen vanwege het feit dat niet alle vragen door alle respondenten zijn beantwoord. Enig advies over hoe hiermee om te gaan?

1
als je je vraag bewerkt en een aantal voorbeeldgegevens toevoegt die gemakkelijk kunnen worden gesneden en in een R-terminal kunnen worden geplakt, dan denk ik dat je binnen een paar minuten verschillende goede antwoorden krijgt. In zijn huidige vorm is het moeilijk om de structuur van uw gegevens echt te begrijpen. U kunt de resultaten van dput (head (yourDataStructure)) in de vraag plakken en dan hebben we precies dezelfde gegevens waarmee u werkt. Andere goede tips hier . Wat ik in uw voorbeeldgegevens niet zie, zijn de kolomkoppen, moeten we aannemen dat u die later toevoegt?
toegevoegd de auteur Chase, de bron
De suggesties van @ Chase zijn goed, maar ik zou een verzoek toevoegen voor de structuur van de onbewerkte CSV die u probeert in te lezen.
toegevoegd de auteur Joshua Ulrich, de bron
bedankt iedereen voor de grondige antwoorden en suggesties voor hoe je op de meest bruikbare vragen kunt antwoorden! Ik heb nu veel om mee te werken, ik waardeer het echt.
toegevoegd de auteur elfs, de bron

2 antwoord

Je zult jezelf waarschijnlijk veel moeite besparen om het csv-bestand in de juiste indeling in de eerste plaats te lezen. read.csv is een krachtige functie die bestand moet zijn tegen uw gegevens, en dit mungen zou niet nodig moeten zijn.

Hier gaat het echter:

x <- matrix(test, byrow=TRUE, ncol=5)
x <- x <- sub("Q-\\w+,", "", x)
x[x==","] <- NA
x <- cbind(matrix(unlist(strsplit(x[, 1], ",")), byrow=TRUE, ncol=2), x[, -1])
x <- as.data.frame(x, stringsAsFactors=FALSE)
names(x) <- c("ID", "Name", "Gender", "Age", "Major", "V1")

Dit resulteert in:

x

      ID        Name Gender   Age            Major   V1
1 [1234]   Bob Smith   Male 18-25 Computer Science 
2 [5678] Julie Lewis Female 18-25              
2
toegevoegd
Zal dit niet naar beneden vallen als er verschillende aantallen rijen per persoon zijn? Dat was de belangrijkste reden waarom mijn poging veel kludgy was. Ik veronderstelde dat het handmatig proberen om rijen toe te voegen en het werkblad te reinigen, vermeden moest worden.
toegevoegd de auteur thelatemail, de bron
Ik ga er niet van uit nadat ik gisteren handmatig alles heb gedaan aan het repareren van een database met onderzoeksgegevens met inconsistente opmaak. :-P
toegevoegd de auteur thelatemail, de bron
@thelatemail Misschien, maar ik neem aan dat elke persoon hetzelfde aantal rijen heeft. Dat is wat u krijgt van een enquêtedump in een csv-bestand.
toegevoegd de auteur Andrie, de bron
@thelatemail Ouch. Je hebt mijn sympathie.
toegevoegd de auteur Andrie, de bron
bedankt, ik zal waarschijnlijk uiteindelijk weer in het bestand lezen, maar een elegant voorbeeld zien is super handig
toegevoegd de auteur elfs, de bron
yep @thelatemail, er zijn een aantal rijen voor sommige gebruikers, ik ga een paar van je suggesties doen om hiermee om te gaan. Maar ik neem een ​​tijdje de tijd om de leercurve hier op te vijzelen
toegevoegd de auteur elfs, de bron

Dit is een beetje onhandig, maar het werkt.

Dit zijn de gegevens:

test <- c(
"[1234],Bob Smith,",
"Q-0,Male",
"Q-1,18-25",
"Q-2,Computer Science",
",",
"[5678],Julie Lewis",
"Q-0,Female",
"Q-1,18-25",
",",
"[1234],Bob Smith,",
"Q-1,18-25",
"Q-2,Computer Science",
","
)

Hier is de manipulatiecode:

#remove rows with just a comma
test <- test[test!=","]
#find id cases and remove the commas between the id and the name
#and add an id label
idcases <- grep("\\[.*\\]",test)
test[idcases] <- paste("id,",gsub(",","",test[idcases]),sep="")
#find id values positions and end position
idvals <- c(idcases,length(test)+1)
#generate a sequence identifier for each respondent
setid <- rep(1:(length(idvals)-1),diff(idvals))
#put the set id against each value
result1 <- paste(setid,test,sep=",")
#split the strings up and make them a data.frame
result2 <- data.frame(do.call(rbind,strsplit(result1,",")))
#get the final dataset with a reshape
final <- reshape(result2,idvar="X1",timevar="X2",direction="wide")[,-1]
#clean up the names etc
names(final) <- c("name","gender","age","major")
final$id <-  gsub("(\\[.*\\])(.*)","\\1",final$name)
final$name <- gsub("(\\[.*\\])(.*)","\\2",final$name)

Wat geeft:

> final
         name gender   age            major     id
1   Bob Smith   Male 18-25 Computer Science [1234]
5 Julie Lewis Female 18-25              [5678]
8   Bob Smith    18-25 Computer Science [1234]
0
toegevoegd
mooie strategie om ontbrekende waarden voor sommige respondenten aan te pakken
toegevoegd de auteur elfs, de bron