Подтвердить что ты не робот

Cumsum используя ddply

Мне нужно использовать группу по уровням с ddply или aggregate, если это проще. Я не уверен, как это сделать, поскольку мне нужно использовать 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))

но это не подводит итог, на мой взгляд, потому, что столбец часа используется для группы и его разделение на это. Я думаю. Я не уверен, что полностью понимаю, как работает агрегат здесь. Есть ли способ получить требуемый результат с помощью aggregate или ddply?

4b9b3361

Ответ 1

Здесь решение в базе R с использованием ave и 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)
})

Ваш текущий подход не работает отчасти потому, что вы включили "час" в качестве одной из ваших переменных группировки. Другими словами, он видит комбинацию "A + tea + 0" в отличие от "A + tea + 1", но с вашего желаемого результата вы, похоже, просто хотите, чтобы комбинация "A + tea" была группа.

aggregate не будет работать так, как вы ожидаете, потому что он сконденсирует все в data.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

Ответ 2

вы должны использовать 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