2016-07-23 41 views
0

Entschuldigung, wenn dies offensichtlich ist, habe ich etwas gefunden, wenn es einen Index gibt oder für, wenn Spalten fehlen. Aber ich glaube nicht, dass es funktionieren wird.machen Datenrahmen durch die Kombination von Spalten mit Listen mit fehlenden Daten, strsplit, ohne Index

Beispieldaten:

df.test=data.frame(A=c("n,n,y,n" ,"t", "j,k,k") 
        ,B=c("n,y,y,n" ,"" , "k,k,k") 
        ,C=c("n,y,y,n,n","t", "j,k,j") 
        ,D=c(""   ,"" , "k,k,j") 
        ) 

df.test=lapply(df.test, function(x) as.character(x)) 
str(df.test) # looks similar to my data 

List of 4 
$ A: chr [1:3] "n,n,y,n" "t" "j,k,k" 
$ B: chr [1:3] "n,y,y,n" "" "k,k,k" 
$ C: chr [1:3] "n,y,y,n,n" "t" "j,k,j" 
$ D: chr [1:3] "" "" "k,k,j" 

Mein Ziel ist ein Datenrahmen:

A B C D 
n n n NA 
n y y NA 
y y y NA 
n n n NA 
t NA t NA 
j k j k 
k k k k 
k k j j 

I Spalte A möchte die Referenz sein, aber es ist nicht eindeutige Werte hat. Es hat jedoch die maximale Anzahl von Werten erlaubt von jeder Liste (ich hoffe, dass das Sinn macht). Daher sollte der fünfte Wert in C-Liste 1 fallen gelassen werden, dh n y y n n -> n y y n. Auch fehlende Werte müssen hinzugefügt werden (fehlt laut Spalte A). Der zusätzliche Wert in C ist ein Fehler von anderer Software (auf die ich keinen Einfluss habe). Anders als diese zusätzlichen Werte entsprechen sie einander, zB sollten die t's in der gleichen Reihe sein (falls vorhanden).

Das Beste, was ich bis jetzt getan habe, ist eine Liste von Vektoren zu machen, die Listen haben unterschiedliche Längen, also kann ich sie nicht zusammensetzen und sie entsprechen nicht.

df3=lapply(df.test, function(x) unlist(strsplit(x,','))) 
str(df3) 

List of 4 
$ A: chr [1:8] "n" "n" "y" "n" ... 
$ B: chr [1:7] "n" "y" "y" "n" ... 
$ C: chr [1:9] "n" "y" "y" "n" ... 
$ D: chr [1:3] "k" "k" "j" 

Antwort

1

Da Sie Spalte A regieren wollen, können wir zunächst die Feldlängen der Textelemente in Spalte A precompute Dies kann mit einem anfänglichen strsplit() Anruf auf df.test[[1L]] getan werden, und dann die lengths() nehmen.

Dann können wir lapply() verwenden, um über alle Spalten zu iterieren und sie mit strsplit() zu teilen. Um sicherzustellen, dass wir jeden aufgeteilten Kettenvektor gemäß der maßgebenden Länge von Spalte A begrenzen, müssen wir jeden aufgeteilten Kettenvektor von 1 bis zu der Länge von Spalte A indizieren, wobei der Indexvektor über seq_len() berechnet wird. Dies kann unter Verwendung von Map() erfolgen, um sowohl den Vektor der aufgeteilten Zeichenfolge als auch den Vektor der vorausberechneten Längen parallel zu durchlaufen. Das Indizieren des geteilten Zeichenkettenvektors bewerkstelligt in geeigneter Weise zwei Dinge: (1) Begrenzt die Länge, und (2) gibt NA für Nacheilindizes zurück, die nicht im geteilten Zeichenkettenvektor der aktuellen Spalte dargestellt sind. Wir können schließlich unlist() die resultierende Liste der geteilten Zeichenkettenvektoren, um einen einzelnen Spaltenvektor zu erhalten, und das Ganze in as.data.frame() wickeln, um die Liste zu data.frame zu zwingen.

ls1 <- lengths(strsplit(df.test[[1L]],',')); 
as.data.frame(lapply(df.test,function(x) 
    unlist(Map(function(ss,l) ss[seq_len(l)],strsplit(x,','),ls1)) 
),stringsAsFactors=F); 
## A B C D 
## 1 n n n <NA> 
## 2 n y y <NA> 
## 3 y y y <NA> 
## 4 n n n <NA> 
## 5 t <NA> t <NA> 
## 6 j k j k 
## 7 k k k k 
## 8 k k j j 
+0

Wow. Ich bin weit davon entfernt, so etwas zu finden. Arbeitete an den Beispieldaten und an den tatsächlichen Daten. Ich habe es geschafft, dass eine verschachtelte Schleife funktioniert, aber ich bin froh, dass ich sie nicht verwenden muss. Danke vielmals. – john

0

Siehe die Antwort von bgoldst oben.

Unten ist was ich dachte, nur für den Fall, dass es für jedermann von Nutzen ist. Es funktioniert an den Beispieldaten, aber nicht an den eigentlichen Daten, sondern nur daran, warum eine viel bessere Antwort gepostet wurde.

Nochmals vielen Dank.

df6=lapply(df.test, function(x) strsplit(x,',')) 

    df7=data.frame() 
    df7=lapply(df7, function(x) as.character(x)) 

    for (i in 1:length(df6$A)){ 
    for (ii in 1:length(df6$A[[i]])){ 
     df7=rbind(df7,sapply(df6,function(x) x[[i]][ii])) 
    } 
    } 

    str(df7) 

    print(df7)