我正在尝试在一个非常大的数据帧(〜220万行)中创建一列,该列计算每个因子水平的1的累积总和,并在达到新的因子水平时重置。以下是一些类似于我自己的基本数据。

itemcode <- c('a1', 'a1', 'a1', 'a1', 'a1', 'a2', 'a2', 'a3', 'a4', 'a4', 'a5', 'a6', 'a6', 'a6', 'a6')
goodp <- c(0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1)
df <- data.frame(itemcode, goodp)

我希望输出变量cum.goodp看起来像这样:
cum.goodp <- c(0, 1, 2, 0, 1, 1, 2, 0, 0, 1, 1, 1, 2, 0, 1)

我得到了很多使用规范的拆分应用组合方法的方法,从概念上讲,这是很直观的,但是我尝试使用以下方法:
k <- transform(df, cum.goodp = goodp*ave(goodp, c(0L, cumsum(diff(goodp != 0)), FUN = seq_along, by = itemcode)))

当我尝试运行此代码时,它非常慢。我知道转换是原因(“by”也无济于事)的一部分。 itemcode变量有超过70K个不同的值,因此应该将其向量化。有没有一种使用cumsum将其向量化的方法?如果没有,任何帮助将不胜感激。非常感谢。

最佳答案

通过修改后的示例输入/输出,您可以使用以下基本R方法(以及其他方法):

transform(df, cum.goodpX = ave(goodp, itemcode, cumsum(goodp == 0), FUN = cumsum))
#   itemcode goodp cum.goodp cum.goodpX
#1        a1     0         0          0
#2        a1     1         1          1
#3        a1     1         2          2
#4        a1     0         0          0
#5        a1     1         1          1
#6        a2     1         1          1
#7        a2     1         2          2
#8        a3     0         0          0
#9        a4     0         0          0
#10       a4     1         1          1
#11       a5     1         1          1
#12       a6     1         1          1
#13       a6     1         2          2
#14       a6     0         0          0
#15       a6     1         1          1

注意:我在输入cum.goodp中添加了df列,并创建了一个新的cum.goodpX列,因此您可以轻松地将两者进行比较。

但是,当然,您可以对软件包使用许多其他方法,例如@MartinMorgan建议的方法或使用dplyr或data.table的方法,仅列举两个选项。对于大型数据集,这些方法可能比基本R方法要快得多。

这是在dplyr中完成的方法:
library(dplyr)
df %>%
   group_by(itemcode, grp = cumsum(goodp == 0)) %>%
   mutate(cum.goodpX = cumsum(goodp))

您问题的注释中已经提供了一个data.table选项。

10-06 04:17