13

ddplyまたはaggregateのレベルでgroupbyを使用する方が簡単な場合は、それを使用する必要があります。集計関数としてcumsumを使用する必要があるため、これを行う方法がよくわかりません。これは私のデータがどのように見えるかです:

level1      level2  hour     product 
A           tea     0          7
A           tea     1          2
A           tea     2          9
A           coffee  17         7
A           coffee  18         2
A           coffee  20         4
B           coffee  0          2
B           coffee  1          3
B           coffee  2          4
B           tea     21         3
B           tea     22         1

期待される出力:

A     tea     0   7
A     tea     1   9
A     tea     2   18
A     coffee  17  7
A     coffee  18  9
A     coffee  20  13
B     coffee  0   2
B     coffee  1   5
B     coffee  2   9
B     tea     21  3
B     tea     22  4

使ってみました

ddply(dd,c("level1","level2","hour"),summarise,cumsum(product))

しかし、それは私が思うに要約されていません。なぜなら、時間列がgroup byに使用され、それによって分割されているからです。集計またはddplyを使用して必要な出力を取得する方法はありますか?

4

3 に答える 3

16

aveとを使用したベースRのソリューションは次のwithinとおりです。

within(mydf, {
  cumsumProduct <- ave(product, level1, level2, FUN = cumsum)
})
#    level1 level2 hour product cumsumProduct
# 1       A    tea    0       7             7
# 2       A    tea    1       2             9
# 3       A    tea    2       9            18
# 4       A coffee   17       7             7
# 5       A coffee   18       2             9
# 6       A coffee   20       4            13
# 7       B coffee    0       2             2
# 8       B coffee    1       3             5
# 9       B coffee    2       4             9
# 10      B    tea   21       3             3
# 11      B    tea   22       1             4

もちろん、既存の製品列を削除する場合は、コマンドを次のように変更して、現在の「製品」列を上書きできます。

within(mydf, {
  product <- ave(product, level1, level2, FUN = cumsum)
})

グループ化変数の1つとして「時間」を含めたため、現在のアプローチは部分的に機能しません。つまり、「A + tea + 0」の組み合わせは、「A + tea + 1」とは異なるように見えますが、目的の出力からは、単に「A+tea」の組み合わせをグループ。

aggregatedata.frame「level1」と「level2」の一意の組み合わせの数(この場合は4行)と同じ行数ですべてが凝縮されるため、期待どおりに機能しません。集約された列はになりますlist。値は正しいでしょうが、あまり役に立ちません。

aggregateこれとその出力は次のとおりです。

> aggregate(product ~ level1 + level2, mydf, cumsum)
  level1 level2  product
1      A coffee 7, 9, 13
2      B coffee  2, 5, 9
3      A    tea 7, 9, 18
4      B    tea     3, 4
于 2013-02-21T10:21:30.883 に答える
7

transformの代わりに使用する必要がありますsummarise

# you should probably order your `level2` first
dd$level2 <- factor(dd$level2, levels=c("tea", "coffee"))
# and transform using level1 and level2 alone, not hour
# if you use hour, the groups will be for each row
ddply(dd, .(level1, level2), transform, product=cumsum(product))

#    level1 level2 hour product
# 1       A    tea    0       7
# 2       A    tea    1       9
# 3       A    tea    2      18
# 4       A coffee   17       7
# 5       A coffee   18       9
# 6       A coffee   20      13
# 7       B    tea   21       3
# 8       B    tea   22       4
# 9       B coffee    0       2
# 10      B coffee    1       5
# 11      B coffee    2       9
于 2013-02-21T10:19:42.330 に答える
0

これを参照している人は、の使用を避けたいと思うかもしれませんplyr::ddply。これがdplyr解決策です。

library(dplyr)
output <- dd %>%
  group_by(level1, level2) %>%
  mutate(product_sum = cumsum(product)) %>%
  ungroup()
output

product_sumここで、新しい列の名前が付けられていることに注意してください。代わりに使用できますproduct。次に、元の質問がそれを実行することを好み、出力に両方の列がないように見えるため、元の製品列が上書きされます。

データ:

level1 <- c(rep("A",6), rep("B",5))
level2 <- c(rep("tea",3), rep("coffee",6), rep("tea",2))
hour <- c(0,1,2,17,18,20,0,1,2,21,22)
product <- c(7,2,9,7,2,4,2,3,4,3,1)

dd <- data.frame(level1, level2, hour, product)
于 2022-02-24T17:01:23.810 に答える