计算每行的累计总和

lok*_*art 20 r

我试图使用以下代码计算每行的累积总和:

df <- data.frame(count=1:10)

for (loop in (1:nrow(df)))
    {df[loop,"acc_sum"] <- sum(df[1:loop,"count"])}
Run Code Online (Sandbox Code Playgroud)

但我不喜欢这里的显式循环,我该如何修改呢?

Cha*_*ase 46

你要 cumsum()

df <- within(df, acc_sum <- cumsum(count))
Run Code Online (Sandbox Code Playgroud)


Ite*_*tor 11

你也可以试试mySum = t(apply(df, 1, cumsum)).

转置是在那里,因为结果出来转换,原因我还没有确定.

我确信有很好的解决方案plyr,例如ddply和多核方法.

  • 结果中的第一个维度与单个调用FUN的长度相匹配,然后接下来是MARGIN维度.所以它不是那么"转置",因为它只是2D中的一个微不足道的结果.这是我对此的解读?无论如何都适用."如果每次调用'FUN'都会返回一个长度为'n'的向量,那么'apply'会返回一个维度为'c(n,dim(X)[MARGIN])'的数组,如果'n> 1'." (2认同)

Aar*_*ica 8

为了复制OP的结果cumsum,正如Chase的答案所示,该功能就是所需要的.然而,OP的"每行"的措辞可能表示对矩阵或数据帧的累积和的兴趣.

对于data.frame的逐列cumsums,有趣的cumsum是,再一次需要! cumsum是一个原语Math,它是泛型函数组的一部分,它是为数据帧定义的,它将函数应用于每一列; 在代码中,它就是这样做的:x[] <- lapply(x, .Generic, ...).

> foo <- matrix(1:6, ncol=3)
> df <- data.frame(foo)
> df
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6
> cumsum(df)
  X1 X2 X3
1  1  3  5
2  3  7 11
Run Code Online (Sandbox Code Playgroud)

有趣的是,sum它不是通用功能组的一部分Math,而是其一部分Summary; 对于数据帧,该组首先将数据帧转换为矩阵,然后调用泛型,因此sum不返回按列的总和,而是返回总和:

> sum(df)
[1] 21
Run Code Online (Sandbox Code Playgroud)

这种差异(在我看来)最有可能是因为cumsum返回与原始尺寸相同的矩阵,但sum不会.

对于行式累积和,没有一个函数可以复制我所知道的这种行为; 迭代器的解决方案可能是最简单的解决方案之一.

如果速度是一个问题,那么用C语言写它几乎肯定是最快和最简单的; 但是,通过使用简单的for循环,它可以为长循环加速一点(~2x?).

rowCumSums <- function(x) {
  for(i in seq_len(dim(x)[1])) { x[i,] <- cumsum(x[i,]) }; x
}
colCumSums <- function(x) {
  for(i in seq_len(dim(x)[2])) { x[,i] <- cumsum(x[,i]) }; x
}
Run Code Online (Sandbox Code Playgroud)

通过使用plain可以加快速度,cumsum并在到达列末尾时减去总和.对于行累积总和,需要转置两次.

colCumSums2 <- function(x) {
  matrix(cumsum(rbind(x,-colSums(x))), ncol=ncol(x))[1:nrow(x),]
}
rowCumSums2 <- function(x) {
  t(colCumSums2(t(x)))
}
Run Code Online (Sandbox Code Playgroud)

这真的是一个黑客.不要这样做.