Je veux créer une nouvelle colonne dans un data.table calculée à partir de la valeur actuelle d'une colonne et de la précédente d'une autre. Est-il possible d'accéder aux lignes précédentes?
Par exemple.:
> DT <- data.table(A=1:5, B=1:5*10, C=1:5*100)
> DT
A B C
1: 1 10 100
2: 2 20 200
3: 3 30 300
4: 4 40 400
5: 5 50 500
> DT[, D := C + BPreviousRow] # What is the correct code here?
La bonne réponse devrait être
> DT
A B C D
1: 1 10 100 NA
2: 2 20 200 210
3: 3 30 300 320
4: 4 40 400 430
5: 5 50 500 540
Avec shift()
implémenté dans v1.9.6 , cela est assez simple.
DT[ , D := C + shift(B, 1L, type="lag")]
# or equivalently, in this case,
DT[ , D := C + shift(B)]
De NOUVELLES :
- La nouvelle fonction
shift()
implémente rapidementlead/lag
De vector , list , data.frames ou data.tables . Il faut un argumenttype
qui peut être soit "lag" (par défaut) ou "lead ". Il permet une utilisation très pratique avec:=
Ouset()
. Par exemple:DT[, (cols) := shift(.SD, 1L), by=id]
. Veuillez consulter?shift
Pour plus d'informations.
Voir l'historique pour les réponses précédentes.
En utilisant dplyr
vous pourriez faire:
mutate(DT, D = lag(B) + C)
Qui donne:
# A B C D
#1: 1 10 100 NA
#2: 2 20 200 210
#3: 3 30 300 320
#4: 4 40 400 430
#5: 5 50 500 540
Plusieurs personnes ont répondu à la question spécifique. Voir le code ci-dessous pour une fonction à usage général que j'utilise dans des situations comme celle-ci qui peuvent être utiles. Plutôt que de simplement obtenir la ligne précédente, vous pouvez aller autant de lignes dans le "passé" ou le "futur" que vous le souhaitez.
rowShift <- function(x, shiftLen = 1L) {
r <- (1L + shiftLen):(length(x) + shiftLen)
r[r<1] <- NA
return(x[r])
}
# Create column D by adding column C and the value from the previous row of column B:
DT[, D := C + rowShift(B,-1)]
# Get the Old Faithul eruption length from two events ago, and three events in the future:
as.data.table(faithful)[1:5,list(eruptLengthCurrent=eruptions,
eruptLengthTwoPrior=rowShift(eruptions,-2),
eruptLengthThreeFuture=rowShift(eruptions,3))]
## eruptLengthCurrent eruptLengthTwoPrior eruptLengthThreeFuture
##1: 3.600 NA 2.283
##2: 1.800 NA 4.533
##3: 3.333 3.600 NA
##4: 2.283 1.800 NA
##5: 4.533 3.333 NA
D'après le commentaire de @Steve Lianoglou ci-dessus, pourquoi ne pas simplement:
DT[, D:= C + c(NA, B[.I - 1]) ]
# A B C D
# 1: 1 10 100 NA
# 2: 2 20 200 210
# 3: 3 30 300 320
# 4: 4 40 400 430
# 5: 5 50 500 540
Et évitez d'utiliser seq_len
ou head
ou toute autre fonction.
Après la solution d'Arun, des résultats similaires peuvent être obtenus sans se référer à .N
> DT[, D := C + c(NA, head(B, -1))][]
A B C D
1: 1 10 100 NA
2: 2 20 200 210
3: 3 30 300 320
4: 4 40 400 430
5: 5 50 500 540
Voici ma solution intuitive:
#create data frame
df <- data.frame(A=1:5, B=seq(10,50,10), C=seq(100,500, 100))`
#subtract the shift from num rows
shift <- 1 #in this case the shift is 1
invshift <- nrow(df) - shift
#Now create the new column
df$D <- c(NA, head(df$B, invshift)+tail(df$C, invshift))`
Ici, invshift
, le nombre de lignes moins 1, est 4. nrow(df)
vous donne le nombre de lignes dans un cadre de données ou dans un vecteur. De même, si vous souhaitez conserver des valeurs antérieures, soustrayez à nrow 2, 3, ... etc., et insérez également NA au début.
J'ai ajouté un argument de remplissage et changé quelques noms et je l'ai appelé shift
. https://github.com/geneorama/geneorama/blob/master/R/shift.R