按相同 ID 对所有列求和
Sum all columns, by same ID
我有 12 个 data.frames 具有相同的变量,但行号不同。这些 data.frames 有一个列 ID,并且这些 ID 的 90% 在所有 data.frames 中都是相同的。
ID <- c(1:10)
wage <- c(1500:1509)
bonus <- c(1000:1009)
df1 <- data.frame(ID,wage,bonus)
ID <- c(1:11)
wage <- c(1800:1810)
bonus <- c(1200:1210)
df2 <- data.frame(ID,wage,bonus)
为了简化流程,data.frames 存储在一个列表中,因此您可以访问:df[[1]]、df[[2]].
我想创建一个新的数据框,我们称之为 new_df,具有相同的变量,但按 ID 对所有列值求和(并且仅对所有 data.frames 中存在的 ID 求和) ).由于每个df都有每个月的工资和奖金,所以我这里的目标是拿到年薪。
如果有人能提供帮助,我将不胜感激。
如果你有一个列表 dfs
你可以使用这个 dplyr
解决方案
library(dplyr)
dfs <- list(df1, df2)
bind_rows(dfs) %>%
group_by(ID) %>%
summarise(wage = sum(wage), bonus = sum(bonus))
这个有用吗:
> ID <- c(1:10)
> wage <- c(1500:1509)
> bonus <- c(1000:1009)
>
> df1 <- data.frame(ID,wage,bonus)
>
> ID <- c(1:11)
> wage <- c(1800:1810)
> bonus <- c(1200:1210)
>
> df2 <- data.frame(ID,wage,bonus)
>
> ID <- c(1:20)
> wage <- c(2001:2020)
> bonus <- c(1301:1320)
>
> df3 <- data.frame(ID,wage,bonus)
>
> mylist <- list(df1, df2, df3)
>
> my_df <- do.call(rbind, mylist)
>
> my_df %>% group_by(ID) %>% filter(n() == length(mylist)) %>% summarise(tot_wage = sum(wage), tot_bonus = sum(bonus))
`summarise()` ungrouping output (override with `.groups` argument)
# A tibble: 10 x 3
ID tot_wage tot_bonus
<int> <int> <int>
1 1 5301 3501
2 2 5304 3504
3 3 5307 3507
4 4 5310 3510
5 5 5313 3513
6 6 5316 3516
7 7 5319 3519
8 8 5322 3522
9 9 5325 3525
10 10 5328 3528
>
如果您想选择 select 任意数量的列:
> my_func <- function(df, summary_vars){
+ df %>%
+ summarise(across({{summary_vars}}, sum))
+ }
> my_df %>% group_by(ID) %>% filter(n() == length(mylist)) %>% my_func(wage)
`summarise()` ungrouping output (override with `.groups` argument)
# A tibble: 10 x 2
ID wage
<int> <int>
1 1 5301
2 2 5304
3 3 5307
4 4 5310
5 5 5313
6 6 5316
7 7 5319
8 8 5322
9 9 5325
10 10 5328
> my_df %>% group_by(ID) %>% filter(n() == length(mylist)) %>% my_func(bonus)
`summarise()` ungrouping output (override with `.groups` argument)
# A tibble: 10 x 2
ID bonus
<int> <int>
1 1 3501
2 2 3504
3 3 3507
4 4 3510
5 5 3513
6 6 3516
7 7 3519
8 8 3522
9 9 3525
10 10 3528
> my_df %>% group_by(ID) %>% filter(n() == length(mylist)) %>% my_func(c(wage,bonus))
`summarise()` ungrouping output (override with `.groups` argument)
# A tibble: 10 x 3
ID wage bonus
<int> <int> <int>
1 1 5301 3501
2 2 5304 3504
3 3 5307 3507
4 4 5310 3510
5 5 5313 3513
6 6 5316 3516
7 7 5319 3519
8 8 5322 3522
9 9 5325 3525
10 10 5328 3528
>
抛出另一个选项,如果你有一个包含所有数据框的列表,你可以使用 purrr::map_dfr
将它们绑定在一起。在这种情况下,被映射的函数只是 return 数据帧,因此它与 bind_rows
没有什么不同。但是如果你想在绑定每个数据帧之前对它们做一些事情(例如过滤器),map_dfr
是一个不错的选择。
此外,如果您想按 ID 对 所有 列值求和,您可以使用 summarize_all
.
library(tidyverse)
list(df1, df2) %>%
map_dfr(.f = ~.) %>%
group_by(ID) %>%
summarize_all(sum)
编辑:我错过了@Karthik S 得到的过滤步骤。 filter(n() == length(df_lst))
是一个不错的解决方案。
df_lst <- list(df1, df2)
df_lst %>%
map_dfr(.f = ~.) %>%
group_by(ID) %>%
filter(n() == length(df_lst)) %>%
summarize_all(sum)
另一种选择是组合 base R
函数以附加两个数据帧,然后简单地聚合结果。
library(dplyr)
do.call('rbind', list(df1, df2)) %>%
group_by(ID) %>%
filter(n() == length(list(df1, df2))) %>% #as per Karthik S
summarise_all(., sum)
# ID wage bonus
# <int> <int> <int>
# 1 1 3300 2200
# 2 2 3302 2202
# 3 3 3304 2204
# 4 4 3306 2206
# 5 5 3308 2208
# 6 6 3310 2210
# 7 7 3312 2212
# 8 8 3314 2214
# 9 9 3316 2216
# 10 10 3318 2218
我有 12 个 data.frames 具有相同的变量,但行号不同。这些 data.frames 有一个列 ID,并且这些 ID 的 90% 在所有 data.frames 中都是相同的。
ID <- c(1:10)
wage <- c(1500:1509)
bonus <- c(1000:1009)
df1 <- data.frame(ID,wage,bonus)
ID <- c(1:11)
wage <- c(1800:1810)
bonus <- c(1200:1210)
df2 <- data.frame(ID,wage,bonus)
为了简化流程,data.frames 存储在一个列表中,因此您可以访问:df[[1]]、df[[2]].
我想创建一个新的数据框,我们称之为 new_df,具有相同的变量,但按 ID 对所有列值求和(并且仅对所有 data.frames 中存在的 ID 求和) ).由于每个df都有每个月的工资和奖金,所以我这里的目标是拿到年薪。 如果有人能提供帮助,我将不胜感激。
如果你有一个列表 dfs
你可以使用这个 dplyr
解决方案
library(dplyr)
dfs <- list(df1, df2)
bind_rows(dfs) %>%
group_by(ID) %>%
summarise(wage = sum(wage), bonus = sum(bonus))
这个有用吗:
> ID <- c(1:10)
> wage <- c(1500:1509)
> bonus <- c(1000:1009)
>
> df1 <- data.frame(ID,wage,bonus)
>
> ID <- c(1:11)
> wage <- c(1800:1810)
> bonus <- c(1200:1210)
>
> df2 <- data.frame(ID,wage,bonus)
>
> ID <- c(1:20)
> wage <- c(2001:2020)
> bonus <- c(1301:1320)
>
> df3 <- data.frame(ID,wage,bonus)
>
> mylist <- list(df1, df2, df3)
>
> my_df <- do.call(rbind, mylist)
>
> my_df %>% group_by(ID) %>% filter(n() == length(mylist)) %>% summarise(tot_wage = sum(wage), tot_bonus = sum(bonus))
`summarise()` ungrouping output (override with `.groups` argument)
# A tibble: 10 x 3
ID tot_wage tot_bonus
<int> <int> <int>
1 1 5301 3501
2 2 5304 3504
3 3 5307 3507
4 4 5310 3510
5 5 5313 3513
6 6 5316 3516
7 7 5319 3519
8 8 5322 3522
9 9 5325 3525
10 10 5328 3528
>
如果您想选择 select 任意数量的列:
> my_func <- function(df, summary_vars){
+ df %>%
+ summarise(across({{summary_vars}}, sum))
+ }
> my_df %>% group_by(ID) %>% filter(n() == length(mylist)) %>% my_func(wage)
`summarise()` ungrouping output (override with `.groups` argument)
# A tibble: 10 x 2
ID wage
<int> <int>
1 1 5301
2 2 5304
3 3 5307
4 4 5310
5 5 5313
6 6 5316
7 7 5319
8 8 5322
9 9 5325
10 10 5328
> my_df %>% group_by(ID) %>% filter(n() == length(mylist)) %>% my_func(bonus)
`summarise()` ungrouping output (override with `.groups` argument)
# A tibble: 10 x 2
ID bonus
<int> <int>
1 1 3501
2 2 3504
3 3 3507
4 4 3510
5 5 3513
6 6 3516
7 7 3519
8 8 3522
9 9 3525
10 10 3528
> my_df %>% group_by(ID) %>% filter(n() == length(mylist)) %>% my_func(c(wage,bonus))
`summarise()` ungrouping output (override with `.groups` argument)
# A tibble: 10 x 3
ID wage bonus
<int> <int> <int>
1 1 5301 3501
2 2 5304 3504
3 3 5307 3507
4 4 5310 3510
5 5 5313 3513
6 6 5316 3516
7 7 5319 3519
8 8 5322 3522
9 9 5325 3525
10 10 5328 3528
>
抛出另一个选项,如果你有一个包含所有数据框的列表,你可以使用 purrr::map_dfr
将它们绑定在一起。在这种情况下,被映射的函数只是 return 数据帧,因此它与 bind_rows
没有什么不同。但是如果你想在绑定每个数据帧之前对它们做一些事情(例如过滤器),map_dfr
是一个不错的选择。
此外,如果您想按 ID 对 所有 列值求和,您可以使用 summarize_all
.
library(tidyverse)
list(df1, df2) %>%
map_dfr(.f = ~.) %>%
group_by(ID) %>%
summarize_all(sum)
编辑:我错过了@Karthik S 得到的过滤步骤。 filter(n() == length(df_lst))
是一个不错的解决方案。
df_lst <- list(df1, df2)
df_lst %>%
map_dfr(.f = ~.) %>%
group_by(ID) %>%
filter(n() == length(df_lst)) %>%
summarize_all(sum)
另一种选择是组合 base R
函数以附加两个数据帧,然后简单地聚合结果。
library(dplyr)
do.call('rbind', list(df1, df2)) %>%
group_by(ID) %>%
filter(n() == length(list(df1, df2))) %>% #as per Karthik S
summarise_all(., sum)
# ID wage bonus
# <int> <int> <int>
# 1 1 3300 2200
# 2 2 3302 2202
# 3 3 3304 2204
# 4 4 3306 2206
# 5 5 3308 2208
# 6 6 3310 2210
# 7 7 3312 2212
# 8 8 3314 2214
# 9 9 3316 2216
# 10 10 3318 2218