(R) 在具有 2 个变量的 table 对象中应用 运行 行总和

(R) Apply running row sums in a table object with 2 variables

以下是一个复制的数据样本,记录了 300 次缺勤的持续时间。 month 是缺席的第一个月,length 是缺席持续的并发月数。

df <- data.frame("month" = sample(c("jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec"),300, replace = TRUE),
           "length" = sample.int(6, size = 300, replace = TRUE))

df$month <- factor(df$month, levels(df$month)[c(5,4,8,1,9,7,6,2,12,11,10,3)])

使用 table(df$length) 您可以看到 length.

的每个值分别持续了多少次缺席
1  2  3  4  5  6 
55 45 42 56 51 51 

但是因为 length 是递增的,如果我想显示达到(但不一定持续)一定月数的缺勤总数,我可以使用 rev(cumsum(rev(table(df$length)))),它给出:

 1   2   3   4   5   6 
300 245 200 158 102  51

我有兴趣查看 month 的累积视图。 rev(cumsum(rev(table(df$month,df$length)))) returns 向量而不是 table。

我想要的结果是取这个

table(df$month, df$length)

       1  2  3  4  5  6
  jan  5  5  4  5  3  2
  feb  5  7  2  7  9  3
  mar  5  3  2  2  9  4
  apr  6  7  4  4  3 11
  may  5  5  3  5  5  2
  jun  4  4  2  7  4  5
  jul  4  3  5  5  1  4
  aug  4  0  5  3  6  7
  sep  4  5  4  4  3  3
  oct  4  2  1  6  5  4
  nov  5  2  3  5  2  2
  dec  4  2  7  3  1  4

然后变成这样,其中对每个month.

计算length的反向累计数
       1   2   3   4   5   6
  jan  24  19  14  10  5   2
  feb  33  28  21  19  12  3
  mar  25  20  17  15  13  4
  apr  35  29  22  18  14 11
  may  25  20  15  12  7   2
  jun  26  22  18  16  9   5
  jul  22  18  15  10  5   4
  aug  25  21  21  16  13  7
  sep  23  19  14  10  6   3
  oct  22  18  16  15  9   4
  nov  19  14  12  9   4   2
  dec  21  17  15  8   5   4

有没有办法使用 table() 来做到这一点?如果没有,我愿意接受任何解决方案。提前致谢。

我们可以在 reverse 列上使用 rowCumsums,使用索引将 seq (:) 反转为列索引,然后 reverse再次索引

library(matrixStats)
tbl <- table(df$month, df$length)
tbl[] <- rowCumsums(tbl[, ncol(tbl):1])[, ncol(tbl):1]
tbl
#     
#       1  2  3  4  5  6
#  jan 24 19 14 10  5  2
#  feb 33 28 21 19 12  3
#  mar 25 20 17 15 13  4
#  apr 35 29 22 18 14 11
#  may 25 20 15 12  7  2
#  jun 26 22 18 16  9  5
#  jul 22 18 15 10  5  4
#  aug 25 21 21 16 13  7
#  sep 23 19 14 10  6  3
#  oct 22 18 16 15  9  4
#  nov 19 14 12  9  4  2
# dec 21 17 15  8  5  4

或者在 base R 中,它将是 cumsumapply

tbl[] <- t(apply(tbl[, ncol(tbl):1], 1, cumsum))[, ncol(tbl):1]

数据

tbl <-  structure(c(5L, 5L, 5L, 6L, 5L, 4L, 4L, 4L, 4L, 4L, 5L, 4L, 5L, 
    7L, 3L, 7L, 5L, 4L, 3L, 0L, 5L, 2L, 2L, 2L, 4L, 2L, 2L, 4L, 3L, 
    2L, 5L, 5L, 4L, 1L, 3L, 7L, 5L, 7L, 2L, 4L, 5L, 7L, 5L, 3L, 4L, 
    6L, 5L, 3L, 3L, 9L, 9L, 3L, 5L, 4L, 1L, 6L, 3L, 5L, 2L, 1L, 2L, 
    3L, 4L, 11L, 2L, 5L, 4L, 7L, 3L, 4L, 2L, 4L), .Dim = c(12L, 6L
    ), .Dimnames = structure(list(c("jan", "feb", "mar", "apr", "may", 
    "jun", "jul", "aug", "sep", "oct", "nov", "dec"), c("1", "2", 
    "3", "4", "5", "6")), .Names = c("", "")), class = "table")

如果您创建数据框而不是 table-class 对象,您可以使用 Reduce+ 作为函数和 accumulate = T得到一个cumsum。在创建 "table" 之前(在引号中,因为 class 不是 "table")我制作了月份列的因子版本,因此月份将保持相同的顺序。

df$month_fac <- with(df, factor(month, levels = unique(month)))
tbl <- data.table::dcast(df, month_fac ~ length)
tbl[ncol(tbl):2] <- Reduce('+', rev(tbl[-1]),  accumulate = TRUE)

输出是 tbl 对象,但我没有显示它,因为您没有设置种子,因此(随机)值将与问题中显示的输出不同。