2017-02-13 43 views
2

常常我需要計算用於R數據幀的新列(在長形式),衛生組織值應取決於一組的聚集函數(例如和)。舉例來說,我可能會想知道一個產品佔某一天哪些部分銷售:如何使用dplyr根據組上的聚合函數計算新列?

daily fraction = revenue for product i on day d/sum or revenue for all products on day d 

我目前的策略是總結和加盟:

library(dplyr) 

join_summary <- function(data, ...) left_join(data, summarise(data, ...)) 

data = data.frame(
    day = c(1,1,2,2,3,3), 
    product = rep(c("A", "B"), 3), 
    revenue = c(2, 4, 8, 7, 9, 2) 
) 

data2 <- data %>% 
    group_by(day) %>% 
    join_summary(daily_revenue = sum(revenue)) %>% 
    mutate(revenue_fraction = revenue/daily_revenue) 

這工作,但我不知道它是否是反模式。在多行上重複相同的數據(每日收入)似乎效率不高,使用聚合亂丟我的數據框。我的問題是:

  • 是我最喜歡的方式嗎?
  • 是否有這樣做的,最好使用工具從dplyr或更廣泛的Hadleyverse的沒有更好的辦法?
  • 我真的需要我的自定義功能join_summary,或者可以將其與現有的dplyr動詞做什麼? (我寧願留在「管流」中,雖然)
+0

如果這是你想要的輸出,'mutate'似乎工作:'數據%>%GROUP_BY(天)%>%變異(daily_revenue = SUM(收益),revenue_fraction =營業收入/ daily_revenue)'。我會考慮將daily_revenue保持爲反模式,如果在任何地方都屬於日級別的某個單獨表格(如摘要文件)。 – Frank

回答

3

除了使用summarise聚集,可以使用mutate來彙總統計數據分配到全列:

data %>% 
    group_by(day) %>% 
    mutate(
    daily_revenue = sum(revenue), 
    revenue_fraction = revenue/daily_revenue 
) 

這給

Source: local data frame [6 x 5] 
Groups: day [3] 

    day product revenue daily_revenue revenue_fraction 
    <dbl> <fctr> <dbl>   <dbl>   <dbl> 
1  1  A  2    6  0.3333333 
2  1  B  4    6  0.6666667 
3  2  A  8   15  0.5333333 
4  2  B  7   15  0.4666667 
5  3  A  9   11  0.8181818 
6  3  B  2   11  0.1818182 

這是可行的,因爲值sum(revenue)被循環使用以填充組中的所有行。

+0

我認爲,如果我只是做'revenue_fraction =營業收入/總和(收入)',R是不夠的智能緩存sum'的'的結果,因此一遍又一遍地計算呢? – Anders

+1

@安德斯R也在那裏工作。 '總和(收入)'將被計算一次,然後'收入/總和(收入)'將被計算,與分母再循環到使不同長度的兩個向量的分割感。 – Frank