У меня есть два кадра данных, которые выглядят примерно так (они намного больше)
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 (с group_by dplyr), а затем выполняю left_join, но мне нужно сделать это еще несколько раз, и я уверен, что есть лучший способ.
Аналогично комментарию @MrFlick, но я бы предпочел, чтобы первыйsummarise
работал с df2
, а потом добавлял полученный столбец в 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
Субъективно вложенные %>%
кажутся более сложными. Как насчет df2 %>% group_by(center, product) %>% summarise(Volume=sum(volume)) %>% right_join(df1,by=c("center","product"))
?
Совершенно верно. Я привык к left_join
и вложенности. @r2evans
(Не спорю с все, у каждого свой стиль/предпочтения. Я часто вижу этот стиль, поэтому не придираюсь к вам.) Одним из преимуществ magrittr::%>%
является "избегание вложенных вызовов функций" (из magrittr.tidyverse.org), не кажется ли это странным вы считаете, что его использование теперь удобно в сфере, которую он пытается уменьшить? Конечно, вложение одного уровня, как здесь, сильно отличается от чтения calls(nested(multiple(x)))
. Опять же, не критично, просто любопытно и разговорчиво. Я сейчас остановлюсь :-)
Кстати, если ваше обоснование вложения в значительной степени связано с вашим предпочтением left_join
, то всегда можно сделать df2 %>% group_by(center, product) %>% summarise(Volume=sum(volume)) %>% left_join(df1,.,by=c("center","product"))
для того же эффекта, без вложения. Конечно, это не будет работать с базовой |>
трубой, но это не вопрос или ваш ответ ...
О, спасибо за помощь @r2evans, я не знал left_join(df1,.,...)
. Я начну использовать эти альтернативы. И я обновлю ответ. Я ценю все эти предложения, они действительно полезны для улучшения и помогают мне избежать некоторых вредных привычек;)
С
dplyr
это прямое слияние и суммирование:df1 %>% left_join(df2) %>% group_by(center, product, value) %>% summarize(Volume=sum(volume))