我有以下列表,list1
和 list2
:
library(tidyverse)
df1a <- data.frame(
index = c(1, 1, 2, 2),
first_column = c(1, 2, 3, 4),
second_column = c(5, 6, 7, 8)
)
df1b <- data.frame(
index = c(1, 1, 2, 2),
first_column = c(4, 2, 3, 1),
second_column = c(8, 6, 7, 5)
)
list1 <- dplyr::lst(df1a, df1b)
df2a <- data.frame(
index = c(1, 1, 2, 2),
first_column = c(4, 3, 2, 1),
second_column = c(8, 7, 6, 5)
)
df2b <- data.frame(
index = c(1, 1, 2, 2),
first_column = c(8, 2, 6, 5),
second_column = c(4, 3, 7, 1)
)
list2 <- dplyr::lst(df2a, df2b)
这是我想在 list1
和 list2
上运行的函数:
output_mean <- function(subset, name) {
subset %>%
group_by(index) %>%
summarize(across(c(first_column, second_column), ~ mean(.x, na.rm = TRUE))) %>%
mutate(type = name) %>%
print()
}
现在,我可以遍历一个列表:
x <- list()
for (i in names(list1)) {
ps <- output_mean(list1[[i]], i)
x[[paste0(i)]] <- ps
}
#> # A tibble: 2 x 4
#> index first_column second_column type
#> <dbl> <dbl> <dbl> <chr>
#> 1 1 1.5 5.5 df1a
#> 2 2 3.5 7.5 df1a
#> # A tibble: 2 x 4
#> index first_column second_column type
#> <dbl> <dbl> <dbl> <chr>
#> 1 1 3 7 df1b
#> 2 2 2 6 df1b
然后我可以将结果放入一个数据框中:
all1 <- do.call(rbind, x)
all1
#> # A tibble: 4 x 4
#> index first_column second_column type
#> * <dbl> <dbl> <dbl> <chr>
#> 1 1 1.5 5.5 df1a
#> 2 2 3.5 7.5 df1a
#> 3 1 3 7 df1b
#> 4 2 2 6 df1b
但是如果我想将 list1
和 list2
放入 big_list
并循环遍历它怎么办?
这是我尝试过的:
big_list <- list(list1, list2)
y <- list()
for (j in big_list){
x <- list()
for (i in names(j)) {
ps <- output_mean(j[[i]], i)
x[[paste0(i)]] <- ps
}
all = do.call(rbind, x)
}
循环有效,但是只有两个数据帧被附加到 all
中,这是可以理解的,因为外循环覆盖了 all
。
all
#> # A tibble: 4 x 4
#> index first_column second_column type
#> * <dbl> <dbl> <dbl> <chr>
#> 1 1 3.5 7.5 df2a
#> 2 2 1.5 5.5 df2a
#> 3 1 5 3.5 df2b
#> 4 2 5.5 4 df2b
我尝试了很多不同的方法,但我无法将四个数据帧附加到一个 4 x 8 的数据帧中。
由 reprex package (v2.0.0) 于 2021 年 5 月 6 日创建
答案 0 :(得分:1)
我们可以用 length
初始化 'y' 与 length
的 big_list
相同,循环遍历 'big_list' 的序列,(初始化 'x' 也可能更好使用内部列表的 length
。
y <- vector('list', length(big_list))
for (j in seq_along(big_list)){
x <- list()
for (i in seq_along(big_list[[j]])) {
ps <- output_mean(big_list[[j]][[i]], names(big_list[[j]])[i])
x[[i]] <- ps
}
y[[j]] <- do.call(rbind, x)
}
out <- do.call(rbind, y)
-输出
out
# A tibble: 8 x 4
# index first_column second_column type
# <dbl> <dbl> <dbl> <chr>
#1 1 1.5 5.5 df1a
#2 2 3.5 7.5 df1a
#3 1 3 7 df1b
#4 2 2 6 df1b
#5 1 3.5 7.5 df2a
#6 2 1.5 5.5 df2a
#7 1 5 3.5 df2b
#8 2 5.5 4 df2b
使用 map
library(purrr)
out1 <- map_dfr(big_list, ~ imap_dfr(.x, ~ output_mean(.x, .y)))
-输出
out1
# A tibble: 8 x 4
# index first_column second_column type
# <dbl> <dbl> <dbl> <chr>
#1 1 1.5 5.5 df1a
#2 2 3.5 7.5 df1a
#3 1 3 7 df1b
#4 2 2 6 df1b
#5 1 3.5 7.5 df2a
#6 2 1.5 5.5 df2a
#7 1 5 3.5 df2b
#8 2 5.5 4 df2b
答案 1 :(得分:1)
我建议将 big_list
存储为串联列表而不是嵌套列表。
big_list <- c(list1, list2)
如果您这样做,您的原始代码将按原样运行 -
y <- list()
for (i in names(big_list)) {
ps <- output_mean(big_list[[i]], i)
y[[paste0(i)]] <- ps
}
all = do.call(rbind, y)
all
# index first_column second_column type
#* <dbl> <dbl> <dbl> <chr>
#1 1 1.5 5.5 df1a
#2 2 3.5 7.5 df1a
#3 1 3 7 df1b
#4 2 2 6 df1b
#5 1 3.5 7.5 df2a
#6 2 1.5 5.5 df2a
#7 1 5 3.5 df2b
#8 2 5.5 4 df2b
使用 purrr
也更容易应用该函数:
purrr::imap_dfr(big_list, output_mean)
和基础 R :
do.call(rbind, Map(output_mean, big_list, names(big_list)))