下面是问题的简化版本,其中涉及转换多个输入表并将转换后的输出连接到单个表中。
处理并汇总了三个输入表,产生了三个具有相同x
列的输出表。 x
因此可以用作索引变量,以将表与left_join
组合在一起。
out_all
是所需的最终输出表,具有索引列x
和摘要列d
,e
和f
。
此代码可实现所需的输出,但对处理大量输入表而言效率不高。
我希望实现的目标,也许使用purr::map
函数或循环
结构,是将新的摘要列迭代连接到输出表的当前版本。我不想暂停工作流以保存最新的输出,而是希望将输出反馈回循环的开头,以使其形成自身下一个版本的LHS,并在RHS上添加新的摘要列。
在此先感谢您的帮助!
library(tidyverse)
in1 <- tribble(
~x, ~a,
1, 1,
1, 2,
1, 3,
2, 4,
3, 5
)
in2 <- tribble(
~x, ~b,
1, 1,
2, 2,
2, 3,
2, 4,
3, 5
)
in3 <- tribble(
~x, ~c,
1, 1,
2, 2,
3, 3,
3, 4,
3, 5
)
out1 <- in1 %>%
group_by(x) %>%
summarize(d = mean(a))
out2 <- in2 %>%
group_by(x) %>%
summarize(e = mean(b))
out12 <- left_join(out1, out2, by = 'x')
out3 <- in3 %>%
group_by(x) %>%
summarize(f = mean(c))
out_all <- left_join(out12, out3, by = 'x')
答案 0 :(得分:1)
我们将所有数据集对象放入list
中,使用map
在mean
中按list
进行分组,然后将reduce
分组为一个dataste
library(tidyverse)
out <- mget(ls(pattern = "^in\\d+$")) %>%
map(~ .x %>%
group_by(x) %>%
summarise_if(is.numeric, mean)) %>%
reduce(left_join)
此外,如果我们想用不同的方式命名列
mget(ls(pattern = "^in\\d+$")) %>%
map2(., c("d", "e", "f"), ~
.x %>%
group_by(x) %>%
summarise(!! .y := mean(!! rlang::sym(names(.)[2])))) %>%
reduce(left_join)
答案 1 :(得分:0)
对于大量输入表,先合并表然后汇总值而不是先汇总值然后再(递归)合并表,可能会更有效。这是一个带有26个输入表(已简化为单个小标题列表)的小型演示:
library(microbenchmark)
library(purrr)
library(dplyr)
## data
in_dfs <- map(LETTERS, function(var) {
tibble(x = sample(1:3, 5, replace = TRUE), !!var := 1:5)
}) %>%
setNames(paste0("in", seq_along(LETTERS)))
## first combine then summarize
out_tidyverse1 <- function(input)
do.call(bind_rows, input) %>%
group_by(x) %>%
summarize_all(~mean(.x, na.rm = TRUE))
## first summarize then combine
out_tidyverse2 <- function(input)
map(input, ~ .x %>%
group_by(x) %>%
summarise_if(is.numeric, mean)) %>%
reduce(left_join)
microbenchmark(out_tidyverse1(in_dfs), out_tidyverse2(in_dfs))
#> Unit: microseconds
#> expr min lq mean median uq
#> out_tidyverse1(in_dfs) 891.425 1052.342 1356.81 1186.545 1345.594
#> out_tidyverse2(in_dfs) 20482.967 23807.713 26453.08 26144.013 28163.417
#> max neval cld
#> 6790.026 100 a
#> 36884.574 100 b
NB:例如,使用data.table可能会更有效。 data.table的rbindlist
答案 2 :(得分:0)
回到您的第一条评论,如果您的原始输入是单个宽表,为什么不gather
感兴趣的列并使用dplyr
到group_by
和summarise
他们几步?如果不需要这些临时表,则不需要创建各种临时表?
df <- data.frame(id=1:5,matrix(runif(n=26*5),ncol=26))
df %>% gather(k,v,-id) %>% group_by(id) %>%
summarise(m=mean(v))
# A tibble: 5 x 2
id m
<int> <dbl>
1 1 0.522
2 2 0.596
3 3 0.535
4 4 0.548
5 5 0.605