【问题标题】:Conditional summing across data frames in RR中跨数据帧的条件求和
【发布时间】:2019-02-24 03:28:34
【问题描述】:

我正在尝试在 R 中复制 SUMIFS 功能。我有两个数据框。

数据框 1

allReported

ID       employeeGroup
1093     Bargaining Unit
1093     Management
1093     Non-Union
55       Bargaining Unit
55       Management
55       Non-Union

数据框 2

employeeCompSummary

ID       employeeGroup      statBenefits    regularWages
1093     Management         500.00          10000.00
1093     Management         200.00          60000.00
1093     Bargaining Unit    100.00          20000.00
1093     Bargaining Unit    150.00          30000.00
1093     Non-Union          500.00          60000.00
55       Bargaining Unit    750.00          65000.00
55       Bargaining Unit    500.00          75000.00
55       Management         250.00          45000.00
55       Management         850.00          90000.00

我正在尝试汇总 statBenefits(然后是正常工资)以创建一个新表,该表将产生以下结果:

ID       employeeGroup          statBenefits
1093     Bargaining Unit        250.00
1093     Management             700.00
1093     Non-Union              500.00
55       Bargaining Unit        1250.00
55       Management             1100.00
55       Non-Union              0.00

我尝试了以下方法:

library(data.table)
setDT(allReported)[, list(total=sum(statbenefits)), list(employeeCompSummary, employeeGroup)]

并得到以下错误:

Error in `[.data.table`(setDT(allReported), , list(total = sum(statbenefits)),  :   column or expression 1 of 'by' or 'keyby' is type list. Do not quote column names. Usage: DT[,sum(colC),by=list(colA,month(colB))]

我也试过了:

sumTest <- aggregate(allReported, by = list(employeeCompSummary), sum)

并得到以下错误:

**Error in aggregate.data.frame(allReported, by = list(employeeCompSummary),  :   arguments must have same length**

任何人都可以提供任何帮助,我们将不胜感激。我查看了其他似乎可以解决此问题但无法找到有效答案的问题。我将在多件事上完成这项任务,所以我想知道是否有任何人都知道的简单技术。与往常一样,提前感谢 Stack Overflow 上的精彩社区。​​p>

编辑两个示例表的 dput():

allReported <- structure(list(ID = c(1093, 1093, 1093, 1093, 1093, 55, 55, 55,55), employeeGroup = c("Management", "Management", "Bargaining Unit","Bargaining Unit", "Non-Union", "Bargaining Unit", "Bargaining Unit","Management", "Management"), statBenefits = c(500, 200, 100,150, 500, 750, 500, 250, 850), regularWages = c(10000, 60000,20000, 30000, 60000, 65000, 75000, 45000, 90000)), row.names = c(NA,-9L), class = c("tbl_df", "tbl", "data.frame"))

employeeCompSummary <- structure(list(ID = c(1093, 1093, 1093, 55, 55, 55), employeeGroup =c("Bargaining Unit","Management", "Non-Union", "Bargaining Unit", "Management", "Non-Union")), row.names = c(NA, -6L), class = c("tbl_df", "tbl", "data.frame"))

 . 

【问题讨论】:

  • 数据对工作来说是机密的,这就是我列出上面示例表的原因。
  • 你能提供dput格式的表格吗?这将使帮助者更容易

标签: r data.table aggregate


【解决方案1】:

我愿意……

library(data.table)

# don't use setDT, since who knows if it works on tibbeldies
ar = data.table(allReported)
ecs = data.table(employeeCompSummary)

ecs[, total := ar[.SD, on=.(ID, employeeGroup), sum(x.statBenefits), by=.EACHI][, V1]]

     ID   employeeGroup total
1: 1093 Bargaining Unit   250
2: 1093      Management   700
3: 1093       Non-Union   500
4:   55 Bargaining Unit  1250
5:   55      Management  1100
6:   55       Non-Union    NA

即使 OP 请求了一个新表,此代码也会将列添加到 ecs。新表和ecs 之间的行集是相同的,因此携带它们似乎是在浪费脑力。稍后删除列很简单。

如果您想知道这个“更新连接”是如何工作的,请尝试向后工作...

ar[ecs, on=.(ID, employeeGroup), sum(x.statBenefits), by=.EACHI]

# or

ar[ecs, on=.(ID, employeeGroup)]

注意原始代码中的 .SD == ecs。见?.SD。

【讨论】:

    【解决方案2】:

    您可以使用dplyr 和magrittr(对于%&gt;%)包来执行此操作-

    library(dplyr)
    library(magrittr)
    
    df1 <- structure(list(ID = c(1093, 1093, 1093, 55, 55, 55), employeeGroup =c("Bargaining Unit","Management", "Non-Union", "Bargaining Unit", "Management", "Non-Union")), row.names = c(NA, -6L), class = c("tbl_df", "tbl", "data.frame"))
    
    df2 <- structure(list(ID = c(1093, 1093, 1093, 1093, 1093, 55, 55, 55,55), employeeGroup = c("Management", "Management", "Bargaining Unit","Bargaining Unit", "Non-Union", "Bargaining Unit", "Bargaining Unit","Management", "Management"), statBenefits = c(500, 200, 100,150, 500, 750, 500, 250, 850), regularWages = c(10000, 60000,20000, 30000, 60000, 65000, 75000, 45000, 90000)), row.names = c(NA,-9L), class = c("tbl_df", "tbl", "data.frame"))
    
    result <- left_join(df1, df2, by = c("ID", "employeeGroup")) %>%
      group_by(ID, employeeGroup) %>%
      summarize(
        statBenefits = sum(statBenefits, na.rm = T),
        regularWages = sum(regularWages, na.rm = T)
      )
    result
    

    【讨论】:

      【解决方案3】:

      根据您的评论进行编辑:一种方法是使用 data.table 这种方式

      library(data.table)
      dt1 <- data.table(structure(list(ID = c(1093, 1093, 1093, 1093, 1093, 55, 55, 55,55), 
                     employeeGroup = c("Management", "Management", "Bargaining Unit","Bargaining Unit", "Non-Union", "Bargaining Unit", "Bargaining Unit","Management", "Management"), statBenefits = c(500, 200, 100,150, 500, 750, 500, 250, 850), regularWages = c(10000, 60000,20000, 30000, 60000, 65000, 75000, 45000, 90000)), 
                row.names = c(NA,-9L), class = c("tbl_df", "tbl", "data.frame")), key = c("ID", "employeeGroup"))
      
      dt2 <- data.table(structure(list(ID = c(1093, 1093, 1093, 55, 55, 55), employeeGroup =c("Bargaining Unit","Management", "Non-Union", "Bargaining Unit", "Management", "Non-Union")), 
                row.names = c(NA, -6L), class = c("tbl_df", "tbl", "data.frame")), key = c("ID", "employeeGroup"))
      
      
      
      dt1[dt2][, lapply(.SD, sum), .SDcols = c("statBenefits", "regularWages"), by = c("ID", "employeeGroup")]
      

      给了

      ID   employeeGroup statBenefits regularWages
      1:   55 Bargaining Unit         1250       140000
      2:   55      Management         1100       135000
      3:   55       Non-Union           NA           NA
      4: 1093 Bargaining Unit          250        50000
      5: 1093      Management          700        70000
      6: 1093       Non-Union          500        60000
      

      您可以稍后将 NA 值替换为 0

      【讨论】:

      • 返回以下错误:dt[, lapply(.SD, sum), .SDcols = c("statBenefits", "regularWages"), : 'closure' 类型的对象不是子集表
      • dt 是一个函数(尝试?dt),因此当您尝试将它作为data.frame 进行子集化时,您会收到该错误。如果你用不与其他 R 对象冲突的东西重命名数据,它应该解决该错误
      • 使用data.table的.EACHI的另一种可能的方法是employeeCompSummary[allReported, .(statBenefits=if (.N &gt; 0) sum(statBenefits) else 0), on=.(ID, employeeGroup), by=.EACHI]
      • 不错的答案。 OP 现在发布了没有密钥的数据。您可能想展示如何分配密钥和/或使用on=,因此不需要密钥。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-01-01
      • 2013-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-09
      • 2019-03-14
      相关资源
      最近更新 更多