Bereken cumulatieve som (cumsum) per groep

Met dataframe:

df <- data.frame(id = rep(1:3, each = 5)
                 , hour = rep(1:5, 3)
                 , value = sample(1:15))

Ik wil een cumulatieve somkolom toevoegen die overeenkomt met de id:

df
   id hour value csum
1   1    1     7    7
2   1    2     9   16
3   1    3    15   31
4   1    4    11   42
5   1    5    14   56
6   2    1    10   10
7   2    2     2   12
8   2    3     5   17
9   2    4     6   23
10  2    5     4   27
11  3    1     1    1
12  3    2    13   14
13  3    3     8   22
14  3    4     3   25
15  3    5    12   37

Hoe kan ik dit efficiënt doen? Bedankt!


Antwoord 1, autoriteit 100%

df$csum <- ave(df$value, df$id, FUN=cumsum)

aveis de “go-to”-functie als u een per-groepsvector wilt die even lang is als een bestaande vector en deze kan alleen uit die subvectoren worden berekend. Als u verwerking per groep nodig heeft op basis van meerdere “parallelle” waarden, is de basisstrategie do.call(rbind, by(dfrm, grp, FUN)).


Antwoord 2, autoriteit 45%

Om aan de alternatieven toe te voegen, is de syntaxis van data.tableleuk:

library(data.table)
DT <- data.table(df, key = "id")
DT[, csum := cumsum(value), by = key(DT)]

Of, compacter:

library(data.table)
setDT(df)[, csum := cumsum(value), id][]

Het bovenstaande zal:

  • Converteer het data.framenaar een data.tabledoor middel van referentie
  • Bereken de cumulatieve som van de waarde gegroepeerd op id en wijs deze toe door middel van referentie
  • Print (de laatste []daar) het resultaat van de hele operatie

“df” wordt nu een data.tablemet een kolom “csum”.


Antwoord 3, autoriteit 31%

Dplyr gebruiken::

require(dplyr)
df %>% group_by(id) %>% mutate(csum = cumsum(value))

Antwoord 4, autoriteit 15%

Bibliotheek plyrgebruiken.

library(plyr)
ddply(df,.(id),transform,csum=cumsum(value))

Other episodes