R:从一个数据帧到另一个数据帧的 Sumif 等价物

R: Sumif equivalent from one dataframe to another

我有两个看起来有点像这样的数据框(它们要大得多)

df1 <- data.frame(center = c("5012","5012","5025"), 
                  product = c("Apple","Grape","Apple"),
                  value = c(20,30,50))

df1:
            Center   Product     Value
    1       5012       Apple      20
    2       5012       Grape      30
    3       5025       Apple      50

df2 <- data.frame(center = c("5012","5012","5012","5012","5012","5025"),
                  profitCenter = c("A","B","C","D","A","A"),
                  product = c("Apple","Apple","Apple", "Apple","Grape","Apple"),
                  volume = c(20,30,50,70,60,80))

df2:
        Center  Profitcenter  Product   Volume
1       5012        A          Apple     20
2       5012        B          Apple     30
3       5012        C          Apple     50
4       5012        D          Apple     70
5       5012        A          Grape     60
6       5025        A          Apple     80

我想通过“中心”和“产品”从 DF2 中获取“体积”列的总和到 DF1。在 excel 中,我会做一个 sumif,但我正在努力思考如何使用 R 正确地做到这一点:

DF1:
            Center   Product     Value  Volume
    1       5012       Apple      20      170
    2       5012       Grape      30      60
    3       5025       Apple      50      80

目前我正在创建一个 DF2 的聚合版本(使用 dplyr 的 group_by),然后做一个 left_join,但我必须再做几次,我确信有更好的方法。

类似于@MrFlick 的评论,但我更愿意 first summarise in/works with df2 and then 将结果列添加到 df1。但结果和表现是一样的。正如@r2evans 指出的那样:

library(tidyverse)
df2 %>% 
  group_by(center, product) %>% 
  summarise(Volume=sum(volume)) %>% 
  right_join(df1,by=c("center","product"))

或者:

library(tidyverse)
df1 %>% 
  left_join(
    df2 %>% 
      group_by(center,product) %>% 
      summarise(sum(volume)),
  by=c("center","product")
  )

或者(为了避免嵌套,再次感谢@r2evans):

library(tidyverse)
df2 %>% 
  group_by(center, product) %>% 
  summarise(Volume=sum(volume)) %>% 
  left_join(df1,.,by=c("center","product"))

输出:

  center product value sum(volume)
1   5012   Apple    20         170
2   5012   Grape    30          60
3   5025   Apple    50          80