Расчет накопительной суммы для каждой строки - PullRequest
16 голосов
/ 26 сентября 2011

Я пытаюсь рассчитать совокупную сумму для каждой строки, используя следующий код:

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

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

Но мне не нравится явный цикл, как я могу его изменить?

Ответы [ 5 ]

43 голосов
/ 26 сентября 2011

Вы хотите cumsum()

df <- within(df, acc_sum <- cumsum(count))
10 голосов
/ 26 сентября 2011

Вы также можете попробовать mySum = t(apply(df, 1, cumsum)).

Транспонирование здесь, потому что результаты получаются транспонированными, по причине, которую я еще не определил.

Я уверен, что есть прекрасные решения с plyr, такие как ddply и многоядерные методы.

7 голосов
/ 26 сентября 2011

Чтобы воспроизвести результат ОП, все, что нужно, это функция cumsum, как показывает ответ Чейза.Однако формулировка OP «для каждой строки», возможно, указывает на интерес к кумулятивным суммам матрицы или фрейма данных.

Для столбцовых сумм data.frame, что интересно, 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

Интересно, что sum не является частью Math, но входит в группу Summary универсальных функций;для фреймов данных эта группа сначала преобразует фрейм данных в матрицу, а затем вызывает общий тип, поэтому sum возвращает не суммы по столбцам, а общую сумму:

> sum(df)
[1] 21

Это расхождение (в моеммнение) скорее всего потому, что cumsum возвращает матрицу того же размера, что и оригинал, но sum не будет.

Для строковых кумулятивных сумм не существует ни одной функции, которая воспроизводит это поведение, которое язнать о;Решение Iterator, вероятно, является одним из самых простых.

Если скорость является проблемой, почти наверняка было бы самым быстрым и надежным написать ее на C;тем не менее, он немного ускоряется (~ 2x?) для длинных циклов, используя простой цикл for.

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
}

Это можно ускорить, используя обычный cumsum и вычитая сумму такдалеко, когда вы доберетесь до конца столбца.Для кумулятивных сумм строк нужно транспонировать дважды.

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

Хотя это действительно взлом.Не делай этого.

2 голосов
/ 25 ноября 2016

С data.table вы также можете использовать

dt <- as.data.table(df)
dt[, acc_sum := cumsum(count)]
0 голосов
/ 11 июля 2019

Альтернативой cumsum() может быть:

within(df, acc_sum <- Reduce("+", count, accumulate = TRUE))

   count acc_sum
1      1       1
2      2       3
3      3       6
4      4      10
5      5      15
6      6      21
7      7      28
8      8      36
9      9      45
10    10      55
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...