连续将函数应用于嵌套列表,每次应用该函数后,列表将嵌套一次

  • 本文关键字:嵌套 列表 函数 一次 应用于 连续 应用 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)))

首先,我将计算列均值。

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

最新更新