2017-02-13 22 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'は' data%>%group_by(day)%>%mutate(daily_revenue = sum(revenue)、revenue_fraction = revenue/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 = revenue/sum(revenue)'を実行すれば、Rは 'sum'の結果をキャッシュするほどスマートではないので、何度も何度も計算すると思いますか? – Anders

+1

@アンダーズRもその仕事をしています。 'sum(revenue)'は一度計算され、 'revenue/sum(revenue)'が計算され、分母は異なる長さの2つのベクトルの分割を意味するようにリサイクルされます。 – Frank

関連する問題