2010-04-30 7 views
8

Lieber StackOverFlowers (Blumen kurz) kollabiert,meinen Code verbessern, um eine Liste von data.frames

Ich habe eine Liste von data.frames (walk.sample), dass ich in einem einzigen (Riesen zusammenzubrechen möchte) data.frame. Während des Kollabierens möchte ich markieren (eine weitere Spalte hinzufügen), welche Zeilen von welchem ​​Element der Liste stammen. Das ist, was ich bisher habe.

Dies ist der data.frame, der zusammengelegt/gestapelt werden muss.

> walk.sample 
[[1]] 
    walker  x   y 
1073  3 228.8756 -726.9198 
1086  3 226.7393 -722.5561 
1081  3 219.8005 -728.3990 
1089  3 225.2239 -727.7422 
1032  3 233.1753 -731.5526 

[[2]] 
    walker  x   y 
1008  3 205.9104 -775.7488 
1022  3 208.3638 -723.8616 
1072  3 233.8807 -718.0974 
1064  3 217.0028 -689.7917 
1026  3 234.1824 -723.7423 

[[3]] 
[1] 3 

[[4]] 
    walker  x   y 
546  2 629.9041 831.0852 
524  2 627.8698 873.3774 
578  2 572.3312 838.7587 
513  2 633.0598 871.7559 
538  2 636.3088 836.6325 
1079  3 206.3683 -729.6257 
1095  3 239.9884 -748.2637 
1005  3 197.2960 -780.4704 
1045  3 245.1900 -694.3566 
1026  3 234.1824 -723.7423 

Ich habe eine Funktion geschrieben, um eine Spalte hinzuzufügen, dass die Zeilen aus dem Elemente bezeichnen kamen durch Anfügen es zu einem bestehenden data.frame gefolgt.

collapseToDataFrame <- function(x) { # collapse list to a dataframe with a twist 
    walk.df <- data.frame() 
    for (i in 1:length(x)) { 
     n.rows <- nrow(x[[i]]) 
     if (length(x[[i]])>1) { 
      temp.df <- cbind(x[[i]], rep(i, n.rows)) 
      names(temp.df) <- c("walker", "x", "y", "session") 
      walk.df <- rbind(walk.df, temp.df) 
     } else { 
      cat("Empty list", "\n") 
     } 
    } 
    return(walk.df) 
} 


> collapseToDataFrame(walk.sample) 
Empty list 
Empty list 
    walker   x   y session 
3   1 -604.5055 -123.18759  1 
60  1 -562.0078 -61.24912  1 
84  1 -594.4661 -57.20730  1 
9   1 -604.2893 -110.09168  1 
43  1 -632.2491 -54.52548  1 
1028  3 240.3905 -724.67284  1 
1040  3 232.5545 -681.61225  1 
1073  3 228.8756 -726.91980  1 
1091  3 209.0373 -740.96173  1 
1036  3 248.7123 -694.47380  1 

Ich bin gespannt, ob diese elegant mehr getan werden kann, mit vielleicht do.call() oder einer anderen generischen Funktion?

+0

Was genau ist die Sitzungsspalte? Warum möchten Sie leere Liste auf den Bildschirm drucken? – hadley

Antwort

5

Ich behaupte nicht, dies die eleganteste Ansatz zu sein, aber ich denke, es

arbeitet
library(plyr) 

ldply(sapply(1:length(walk.sample), function(i) 
      if (length(walk.sample[[i]]) > 1) 
      cbind(walk.sample[[i]],session=rep(i,nrow(walk.sample[[i]]))) 
    ),rbind) 

EDIT

Nachdem Marek apt Bemerkungen

do.call(rbind,lapply(1:length(walk.sample), function(i) 
      if (length(walk.sample[[i]]) > 1) 
      cbind(walk.sample[[i]],session=i) )) 
+1

'cbind' brauchen keine Replikation, Sie könnten einfach' session = i' schreiben. Und ohne plpl könnte man 'do.call (rbind, sapply (......))' benutzen. – Marek

+0

Hi gd047, möchte ich nur erwähnen, Ihre Lösung würde nicht funktionieren, wenn die data.frame unterschiedliche Anzahl von Zeilen haben. Wenn die Anzahl der Zeilen gleich ist, sind die Ergebnisse nicht korrekt (es gibt eine Mischung aus Zeilen und Spalten. Außerdem gibt es keine Spaltennamen). –

+0

Ich denke, das Ersetzen von 'sapply' mit' lapply' kann helfen. – Marek

6

I Anwendung denke, das wird funktionieren ...

lengths <- sapply(walk.sample, function(x) if (is.null(nrow(x))) 0 else nrow(x)) 
cbind(do.call(rbind, walk.sample[lengths > 1]), 
     session = rep(1:length(lengths), ifelse(lengths > 1, lengths, 0))) 
+0

Sie sollten 'NROW' anstelle von' nrow' verwenden. Für Daten aus Frage wird Ihre Lösung nicht funktionieren. – Marek

+0

Guter Haken, NROW ist eine mögliche Korrektur, aber ich weiß nicht, was das erwartete Verhalten ist, wenn Sie einen 1-reihigen Datenrahmen haben. Ich werde es ändern, indem Sie eine NULL-Prüfung statt ... –

+0

Gute Lösung Jonathan! –

Verwandte Themen