【问题标题】:improve my code for collapsing a list of data.frames改进我的代码以折叠 data.frames 列表
【发布时间】:2011-02-14 03:39:08
【问题描述】:

亲爱的 StackOverFlowers(简称花),

我有一个 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() 或其他更通用的函数更优雅地完成?

【问题讨论】:

  • 会话列到底是什么?为什么要将空列表打印到屏幕上?

标签: list r dataframe


【解决方案1】:

我认为这会起作用...

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)))

【讨论】:

  • 您应该使用NROW 而不是nrow。对于来自问题的数据,您的解决方案将不起作用。
  • 很好,NROW 是一种可能的解决方法,但我不知道当你有一个 1 行数据框时预期的行为是什么。我将通过进行 NULL 检查来更改它...
【解决方案2】:

我并不是说这是最优雅的方法,但我认为它是有效的

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)  ))

【讨论】:

  • cbind 不需要复制,你可以写session=i。如果没有 plyr,可以使用 do.call(rbind, sapply(......))
  • 您好 gd047,我只想提一下,当 data.frame 具有不同的行数时,您的解决方案将不起作用。另外,当行数相同时,结果不正确(行和列混合,也没有列名)
  • 我认为将sapply 替换为lapply 可能会有所帮助。
  • 干得好,伙计们!正是医生所要求的。
猜你喜欢
  • 1970-01-01
  • 2016-10-26
  • 1970-01-01
  • 2017-03-10
  • 1970-01-01
  • 2013-10-29
  • 1970-01-01
  • 1970-01-01
  • 2013-03-09
相关资源
最近更新 更多