2010-04-30 95 views
8

親愛StackOverFlowers(簡稱花)的列表,提高我的代碼崩潰data.frames

我有data.frames(walk.sample)的名單,我想摺疊成一個單一的(巨)data.frame。在崩潰時,我想標記(添加另一列)哪些行來自列表的哪個元素。這是我到目前爲止所做的。

這是需要摺疊/堆疊的data.frame。

> 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 

我已經寫了函數以添加表示從該元件的行進來,隨後將其追加到現有data.frame的列。

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 

我很好奇,這是否可以更優雅的完成,也許do.call()或其他一些比較通用的功能?

+0

會話列究竟是什麼?爲什麼你想要在屏幕上打印空白列表? – hadley 2010-04-30 12:35:44

回答

5

我不是說這是最優雅的方式,但我認爲這是工作

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) 

編輯

應用馬立克氏容易言論

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

'cbind'不需要複製,你可以寫'session = i'。沒有plyr,人們可以使用'do.call(rbind,sapply(......))'。 – Marek 2010-04-30 13:59:38

+0

嗨gd047,我只想提到你的解決方案不會工作時data.frame具有不同的行數。另外,當行數相同時,結果不正確(行與列混合使用,也沒有列名) – 2010-04-30 14:30:05

+0

我認爲用'lapply'替換'sapply'可能會有所幫助。 – Marek 2010-04-30 15:06:44

6

我後認爲這將工作...

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

你應該使用'NROW'而不是'nrow'。對於來自問題的數據,您的解決方案將無法工 – Marek 2010-04-30 15:57:25

+0

良好的捕獲,NROW是一種可能的解決方案,但我不知道當你有一行數據幀時預期的行爲。我會通過做一個NULL檢查來改變它... – 2010-04-30 16:04:46

+0

好的解決方案喬納森! – 2010-04-30 19:55:09