我有一个由数据框组成的嵌套列表。每个数据框具有相同的结构。
df1 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df2 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df3 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df4 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df5 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df6 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df7 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df8 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df9 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df10 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df11 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df12 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df13 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df14 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df15 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df16 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df17 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df18 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df19 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df20 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df21 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df22 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df23 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df24 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df25 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df26 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df27 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
list1 <- list(list(list(df1, df2, df3), list(df4, df5, df6), list(df7, df8, df9)), list(list(df10, df11, df12), list(df13, df14, df15), list(df16, df17, df18)), list(list(df19, df20, df21), list(df22, df23, df24), list(df25, df26, df27)))
首先,我将计算列均值。
list1 <- lapply(list1, function (x) {
lapply(x, function (y) {
lapply(y, colMeans)
})
})
然后,我将在每个列表元素内对数据框进行行绑定。
list2 <- lapply(list1, function (x) {
lapply(x, function (y) {
do.call(rbind, y)
})
})
请注意,现在列表嵌套的级别少了一个。完成此操作后,我将再次计算每个数据框的列均值,但现在,数据框的嵌套比原来少一个级别。
list2 <- lapply(list2, function (x) {
lapply(x, colMeans)
})
执行此操作后,我将再次在列表中对这些数据帧进行行绑定。
list3 <- lapply(list2, function (x) {
do.call(rbind, x)
})
我将继续这种模式,直到我最终得到一个数据框。
list3 <- lapply(list3, colMeans)
final_df <- do.call(rbind, list3)
有没有办法通过编写一个函数来自动执行此操作 第一行绑定 然后计算列均值?我必须这样做很多次。我想知道我是否可以找到一个函数,该函数将在每一步嵌套一次的列表上连续运行。
谢谢!
递归函数可能工作得很好。虽然do.call(rbind, ...)
技术上做到了这一点,但我发现dplyr::bind_rows
或data.table::rbindlist
更强大。
可重现的随机数据:
set.seed(42)
df1 <- data.frame(col1 = sample(LETTERS, 10), col2 = rnorm(10))
df2 <- data.frame(col1 = sample(LETTERS, 10), col2 = rnorm(10))
df3 <- data.frame(col1 = sample(LETTERS, 10), col2 = rnorm(10))
df4 <- data.frame(col1 = sample(LETTERS, 10), col2 = rnorm(10))
df5 <- data.frame(col1 = sample(LETTERS, 10), col2 = rnorm(10))
df6 <- data.frame(col1 = sample(LETTERS, 10), col2 = rnorm(10))
df7 <- data.frame(col1 = sample(LETTERS, 10), col2 = rnorm(10))
df8 <- data.frame(col1 = sample(LETTERS, 10), col2 = rnorm(10))
df9 <- data.frame(col1 = sample(LETTERS, 10), col2 = rnorm(10))
list1 <- list(list(df1, df2, df3), list(df4, df5, df6), list(df7, df8, df9))
执行:
recurse_rbind <- function(x) {
islist <- sapply(x, is.list)
x_notlist <- bind_rows(x[!islist])
x_islist <- bind_rows(lapply(x[islist], recurse_rbind))
bind_rows(list(x_notlist, x_islist))
}
out <- recurse_rbind(list1)
nrow(out)
# [1] 90
head(out)
# col1 col2
# 1 Q -0.09465904
# 2 E 2.01842371
# 3 A -0.06271410
# 4 J 1.30486965
# 5 D 2.28664539
# 6 R -1.38886070
tail(out)
# col1 col2
# 85 G -1.551544822
# 86 I 1.167169549
# 87 U -0.273645701
# 88 C -0.467845325
# 89 R -1.238252328
# 90 O -0.007762034
我不确定期望的结果是什么,因为问题中没有示例输出,问题中给出的代码给出了错误并且一般情况不清楚; 但是,这递归地走遍了结构,可能是您正在寻找的,或者如果不是,可以适当修改。也许 rbind 应该是 cbind 和/或 cbind 应该是 rbind。
Mean <- function(x) { is.num <- sapply(x, is.numeric); colMeans(x[is.num]) }
walk <- function(x) {
if (is.data.frame(x[[1]])) as.data.frame(do.call("rbind", lapply(x, Mean)))
else Mean(do.call("cbind", lapply(x, walk)))
}
walk(list1)
下面是一个基本的 R 解决方案:
df1 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df2 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df3 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df4 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df5 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df6 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df7 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df8 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df9 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df10 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df11 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df12 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df13 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df14 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df15 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df16 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df17 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df18 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df19 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df20 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df21 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df22 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df23 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df24 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df25 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df26 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
df27 <- data.frame(col1 = sample(1:100, 10), col2 = rnorm(10))
list1 <- list(list(list(df1, df2, df3), list(df4, df5, df6), list(df7, df8, df9)), list(list(df10, df11, df12), list(df13, df14, df15), list(df16, df17, df18)), list(list(df19, df20, df21), list(df22, df23, df24), list(df25, df26, df27)))
fxn1 <- function (x) {
if (all(sapply(x, is.data.frame))) {
colMeans(do.call(rbind, x))
} else if (all(sapply(x, is.list))) {
colMeans(do.call(rbind, lapply(x, fxn1)))
}
}
fxn1(list1)