【发布时间】:2011-06-19 07:10:47
【问题描述】:
关于在 SO 上的列表中合并 data.frame 的大多数问题与我在这里想要解决的问题不太相关,但请随时证明我错了。
我有一个 data.frames 列表。我想逐行将行“rbind”到另一个data.frame中。本质上,所有第一行形成一个 data.frame,第二行形成第二个 data.frame,依此类推。 结果将是一个与我的原始 data.frame(s) 中的行数相同长度的列表。到目前为止,data.frames 在维度上是相同的。
这里有一些数据可供使用。
sample.list <- list(data.frame(x = sample(1:100, 10), y = sample(1:100, 10), capt = sample(0:1, 10, replace = TRUE)),
data.frame(x = sample(1:100, 10), y = sample(1:100, 10), capt = sample(0:1, 10, replace = TRUE)),
data.frame(x = sample(1:100, 10), y = sample(1:100, 10), capt = sample(0:1, 10, replace = TRUE)),
data.frame(x = sample(1:100, 10), y = sample(1:100, 10), capt = sample(0:1, 10, replace = TRUE)),
data.frame(x = sample(1:100, 10), y = sample(1:100, 10), capt = sample(0:1, 10, replace = TRUE)),
data.frame(x = sample(1:100, 10), y = sample(1:100, 10), capt = sample(0:1, 10, replace = TRUE)),
data.frame(x = sample(1:100, 10), y = sample(1:100, 10), capt = sample(0:1, 10, replace = TRUE)))
这是我想出的优秀 for 循环。
#solution 1
my.list <- vector("list", nrow(sample.list[[1]]))
for (i in 1:nrow(sample.list[[1]])) {
for (j in 1:length(sample.list)) {
my.list[[i]] <- rbind(my.list[[i]], sample.list[[j]][i, ])
}
}
#solution 2 (so far my favorite)
sample.list2 <- do.call("rbind", sample.list)
my.list2 <- vector("list", nrow(sample.list[[1]]))
for (i in 1:nrow(sample.list[[1]])) {
my.list2[[i]] <- sample.list2[seq(from = i, to = nrow(sample.list2), by = nrow(sample.list[[1]])), ]
}
可以使用矢量化来改善这一点而不会造成太大的脑损伤吗?当然,正确答案将包含一段 sn-p 代码。 “是”作为答案不算数。
编辑
#solution 3 (a variant of solution 2 above)
ind <- rep(1:nrow(sample.list[[1]]), times = length(sample.list))
my.list3 <- split(x = sample.list2, f = ind)
基准测试
我的列表更大,每个 data.frame 有更多行。我对结果进行了基准测试,结果如下:
#solution 1
system.time(for (i in 1:nrow(sample.list[[1]])) {
for (j in 1:length(sample.list)) {
my.list[[i]] <- rbind(my.list[[i]], sample.list[[j]][i, ])
}
})
user system elapsed
80.989 0.004 81.210
# solution 2
system.time(for (i in 1:nrow(sample.list[[1]])) {
my.list2[[i]] <- sample.list2[seq(from = i, to = nrow(sample.list2), by = nrow(sample.list[[1]])), ]
})
user system elapsed
0.957 0.160 1.126
# solution 3
system.time(split(x = sample.list2, f = ind))
user system elapsed
1.104 0.204 1.332
# solution Gabor
system.time(lapply(1:nr, bind.ith.rows))
user system elapsed
0.484 0.000 0.485
# solution ncray
system.time(alply(do.call("cbind",sample.list), 1,
.fun=matrix, ncol=ncol(sample.list[[1]]), byrow=TRUE,
dimnames=list(1:length(sample.list),names(sample.list[[1]]))))
user system elapsed
11.296 0.016 11.365
【问题讨论】:
-
为什么我忘记了拆分?非常好的解决方案!
-
很好的演示。这种情况是我仍然倾向于使用 for 循环的少数情况之一,但很清楚为什么这是一个坏主意:)
-
@jonw,我想这取决于你的追求。如果你有中等或小的数据集,循环就可以了。
-
这个 merged.list = do.call('rbind', sample.list) 怎么样
-
我读到即使问题已经得到解答,也可以奖励赏金。所以我决定去寻找好的答案。然而,这对我来说有点问题,因为 mnel 的 DT 解决方案似乎比我最初计划授予的公认解决方案更好。
标签: r performance list merge dataframe