微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

汇总所有列,并使用相同的ID

如何解决汇总所有列,并使用相同的ID

我有12个data.frame,它们具有相同的变量,但行号不同。这些data.frame具有列ID,并且这些ID中的90%在所有data.frame中都是相同的。

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,bonus)

为简化此过程,将data.frames存储在一个列表中,以便您可以像df [[1]],df [[2]]这样访问。

我想创建一个新的数据框,将其称为new_df,它具有相同的变量,但通过ID(以及仅存在于所有data.frames中的ID)对所有列值进行求和。由于每个df都有每月的工资和奖金,因此我的目标是获得年度工资。 非常感谢有人能帮忙。

解决方法

这项工作:

> 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,bonus)
> 
> ID <- c(1:20)
> wage <- c(2001:2020)
> bonus <- c(1301:1320)
> 
> df3 <- data.frame(ID,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
> 

如果您想选择任意数量的列:

> 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
> 
,

如果您有列表dfs,则可以使用此dplyr解决方案

library(dplyr)

dfs <- list(df1,df2)

bind_rows(dfs) %>% 
  group_by(ID) %>%
  summarise(wage = sum(wage),bonus = sum(bonus))
,

要抛出另一种选择,如果您有一个包含所有数据框的列表,则可以使用purrr::map_dfr将它们绑定在一起。在这种情况下,要映射的函数只是返回数据帧,因此它与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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。