2017-02-13 60 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