2017-02-13 18 views
2

Довольно часто мне нужно вычислить новый столбец для фрейма данных R (в длинной форме), значение whos должно зависеть от агрегатной функции (например, суммы) группы. Например, я мог бы знать, какая доля продаж приходится продукт для любой день:Как вычислить новый столбец в зависимости от агрегатной функции в группе с помощью 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) 

Это работает, но я не уверен, что это анти-шаблон. Кажется немного неэффективным повторять одни и те же данные (ежедневный доход) на нескольких строках, засоряя мой кадр данных с помощью агрегатов. Мои вопросы:

  • Является ли мой curret способ сделать это в порядке?
  • Есть ли лучший способ сделать это, желательно используя инструменты от dplyr или более широкий Hadleyverse?
  • Нужна ли мне моя пользовательская функция join_summary, или это можно сделать с помощью существующих глаголов dplyr? (. Я предпочитаю оставаться в пределах «потока в трубе», хотя)
+0

Если это то, что вы хотите, 'mutate', похоже, работает:' data%>% group_by (day)%>% mutate (daily_revenue = sum (доход), доход_фракция = доход/суточная_выставка) '. Я бы хотел, чтобы ежедневная_реклама была анти-шаблоном, принадлежащим какой-либо отдельной таблице на дневном уровне (например, ваш итоговый), если есть где угодно. – 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

Я предполагаю, что если я просто делаю «доход_фракция = доход/сумма (доход)», R не будет достаточно умен, чтобы кэшировать результат «sum» и, следовательно, вычислять его снова и снова? – Anders

+1

@ Anders R тоже выполняет эту работу. 'sum (income)' будет вычисляться один раз, а затем будет вычисляться «доход/сумма (доход)», при этом знаменатель будет переработан, чтобы иметь смысл разделить два вектора разной длины. – Frank

 Смежные вопросы

  • Нет связанных вопросов^_^