2011-10-19 13 views
5

Si supponga di avere un frame di dati come questo:Calcolare somme cumulative di certi valori

df <- data.frame(Nums = c(1,2,3,4,5,6,7,8,9,10), Cum.sums = NA) 
> df 
    Nums Cum.sums 
1  1  NA 
2  2  NA 
3  3  NA 
4  4  NA 
5  5  NA 
6  6  NA 
7  7  NA 
8  8  NA 
9  9  NA 
10 10  NA 

e si desidera un output come questo:

Nums Cum.sums 
1  1  0 
2  2  0 
3  3  0 
4  4  3 
5  5  5 
6  6  7 
7  7  9 
8  8  11 
9  9  13 
10 10  15 

L'4. elemento della colonna Cum.sum è la somma di 1 e 2, l'elemento 5. della colonna Cum.sum è la somma di 2 e 3 e così via ... Ciò significa che vorrei costruire la somma cumulativa della prima riga e salvarla nella seconda fila. Tuttavia non desidero la somma cumulativa normale ma la somma delle righe dell'elemento 2 sopra la riga corrente più le righe dell'elemento 3 sopra la riga corrente.

Ho già provato a giocare un po 'con la somma e la funzione cumsum ma ho fallito.

Qualche idea?

Grazie!

risposta

3

È possibile utilizzare la funzione embed per creare i ritardi appropriati, rowSums per sommare, quindi ritardare in modo appropriato (ho utilizzato head).

df$Cum.sums[-(1:3)] <- head(rowSums(embed(df$Nums,2)),-2) 
+0

Grazie Joshua! Funziona alla grande! –

0

Non hai bisogno di alcuna funzione speciale, basta usare le normali operazioni di vettori (queste soluzioni sono equivalenti):

df$Cum.sums[-(1:3)] <- head(df$Nums, -3) + head(df$Nums[-1], -2) 

o

with(df, Cum.sums[-(1:3)] <- head(Nums, -3) + head(Nums[-1], -2)) 

o

df$Cum.sums[-(1:3)] <- df$Nums[1:(nrow(df)-3)] + df$Nums[2:(nrow(df)-2)] 

Credo che le prime 3 somme DOVREBBE b e NA, non 0, ma se preferite zeri, è possibile inizializzare le somme prima:

df$Cum.sums <- 0 
+0

Sebbene questa sia una soluzione valida a questo specifico problema, non generalizza in modo appropriato (ad esempio se la somma cumulativa era superiore a 20 righe anziché 2). –

+0

@Joshua, hai ragione, ho postato una soluzione più generale, ma non molto pratica però. La tua soluzione sarà probabilmente la migliore. – TMS

0

Un'altra soluzione, elegante e generale, con la moltiplicazione di matrici - e quindi molto inefficiente per dati di grandi dimensioni. Quindi non è molto pratico, anche se un bel esercizio:

len <- nrow(df) 
sr <- 2 # number of rows to sum 
lag <- 3 
mat <- matrix(
      head(c(
       rep(0, lag * len), 
       rep(rep(1:0, c(sr, len - sr + 1)), len) 
       ), len * len), 
      nrow = 10, byrow = TRUE 
     ) 
mat %*% df$Nums 
Problemi correlati