2016-07-20 2 views
1

Imaginez que nous avons un ensemble de données appelé df, et que cet ensemble de données se compose de deux variables appelées an et x1:Variables de calcul dans R de valeurs multiples dans la même variable

year <- c(2000, 2001, 2002, 2003, 2004) 
x1 <- c(7, 8, 6, 3, 3) 
df <- data.frame(year, x1) 

Ma tâche consiste à calculer deux nouvelles variables sur x1. La première variable est cSum, qui doit refléter la somme des valeurs de x1 pour les deux dernières années. La deuxième variable est cMax, qui doit refléter les valeurs les plus élevées pour x1 au cours des trois dernières années.

Le résultat devrait être le suivant:

year x1 cSum cMax 
2000 7  
2001 8 15  
2002 6 14  8 
2003 3  9  8 
2004 3  6  6 

Comment puis-je calculer les variables csum et CMAX ci-dessus?

Merci!

Répondre

3

En utilisant data.table:

library(data.table) 
setDT(df) 

Tout d'abord, d'une manière alambiquée; depuis transpose est optimisé, ce peut être plus rapide (non testé):

df[ , cSum := transpose(lapply(transpose(shift(x1, 0:1)), sum))] 
df[ , cMax := transpose(lapply(transpose(shift(x1, 0:2)), max))] 

shift est essentiellement un opérateur de retard; nous voulons des décalages 0, 1, et (pour cMax) 2 pour obtenir les périodes 1 et 2 précédentes.

Autre possibilité:

df[ , cSum := rowSums(do.call(cbind, shift(x1, 0:1)))] 
df[ , cMax := do.call(pmax, shift(x1, 0:2))] 

Les deux donnent le même résultat:

df 
# year x1 cSum cMax 
# 1: 2000 7 NA NA 
# 2: 2001 8 15 NA 
# 3: 2002 6 14 8 
# 4: 2003 3 9 8 
# 5: 2004 3 6 6 

La chose ce qui en fait désordre est que lorsque shift renvoie plus d'un retard, il retourne une list; mais malheureusement, cette liste est la transposition de ce dont nous avons besoin (nous faisons une opération par rangée, et elle est produite de manière conviviale). La première option transpose s la liste pour l'obtenir sous une forme plus gérable, puis effectue l'opération par ligne avant transpose revenir dans la forme colonnaire.

La deuxième option convertit la sortie en tableau et effectue des opérations par ligne sur la baie.

+0

est 'transpose' nécessaire, cela permettrait d'atteindre les mêmes ' df [, csum: = (décalage (x1,1, "lag") + shift (x1,2, "lag"))] ' – Bg1850

+1

@ Bg1850 J'allais vraiment ajouter cela, merci de l'avoir signalé. cette approche n'est pas très extensible (en additionnant 10 périodes, par exemple), mais est certainement plus agréable dans ce cas. – MichaelChirico

+0

Oh oui j'ai compris. . – Bg1850

0

Voici une approche utilisant un opérateur de retard. Essentiellement, j'augmente vos données afin de minimiser le besoin de boucles for. Ce faisant, j'augmente la quantité de mémoire utilisée. Cette approche peut sembler logique si vous allez effectuer plus d'analyses de séries temporelles avec cet ensemble de données. Dans la réponse, j'utilise le package zoo, qui est mon package de série temporelle préféré. Cependant, il y a beaucoup d'autres ts, xts (ce qui est généralement plus rapide que zoo), ...

library(zoo) 

year <- c(2000, 2001, 2002, 2003, 2004, 2005) 
x1 <- c(7, 8, 6, 3, 3, 6) 
df <- data.frame(year, x1) 

dfZ <- zoo(df[,-1], order.by = df[,1]) 

dfZ <- merge(dfZ, lag(dfZ, seq(-1, -2))) 

names(dfZ) <- paste0("L", seq(0,2)) 

dfZ$cSum <- rowSums(dfZ[, c("L0", "L1")]) 
dfZ$cMax <- apply(dfZ[, c("L0", "L1", "L2")], 1, max)