Quiero crear una nueva columna en un data.table calculado a partir del valor actual de una columna y el anterior de otra. ¿Es posible acceder a filas anteriores?
P.ej:
> 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 respuesta correcta debe ser
> 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
r
data.table
Korone
fuente
fuente

DT <- data.table(A=..., key = "A")Respuestas:
Con
shift()implementado en v1.9.6 , esto es bastante sencillo.DT[ , D := C + shift(B, 1L, type="lag")] # or equivalently, in this case, DT[ , D := C + shift(B)]De NEWS :
Consulte el historial para obtener respuestas anteriores.
fuente
.Nel número de fila actual o algo así? Siento preguntar aquí, pero parece que no puedo encontrarlo en los archivos de ayuda ....Iútil, que contiene los índices de fila para las filas en el grupo actual..SDejemplo: estaba tratando de usar alapplyy obteniendo resultados extravagantes. esto es mucho más sencillo.Usando
dplyrusted podría hacer:Lo que da:
# 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 540fuente
Varias personas han respondido a la pregunta específica. Consulte el código a continuación para ver una función de propósito general que uso en situaciones como esta y que puede ser útil. En lugar de simplemente obtener la fila anterior, puede ir tantas filas en el "pasado" o en el "futuro" como desee.
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 NAfuente
data.tablepaquete, pero por desgracia ...shiftha agregado una función similar llamada adata.tablepartir de la versión 1.9.5. Vea la respuesta actualizada de @Arun.Basado en el comentario de @Steve Lianoglou anterior, ¿por qué no solo:
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 540Y evitar el uso
seq_lenoheado cualquier otra función.fuente
.Iconseq_len(.N)Siguiendo la solución de Arun, se pueden obtener resultados similares sin hacer referencia a
.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 540fuente
.Nestá disponible) es principalmente una elección estética. No soy consciente de ninguna diferencia importante.Agregué un argumento de relleno y cambié algunos nombres y lo llamé
shift. https://github.com/geneorama/geneorama/blob/master/R/shift.Rfuente
Aquí está mi solución intuitiva:
#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))`Aquí
invshift, el número de filas menos 1 es 4. lenrow(df)proporciona el número de filas en un marco de datos o en un vector. Del mismo modo, si desea tomar valores aún anteriores, reste de nrow 2, 3, ... etc, y también coloque NA en consecuencia al principio.fuente
se puede hacer en bucle.
# Create the column D DT$D <- 0 # for every row in DT for (i in 1:length(DT$A)) { if(i==1) { #using NA at first line DT[i,4] <- NA } else { #D = C + BPreviousRow DT[i,4] <- DT[i,3] + DT[(i-1), 2] } }Usando un for, incluso puede usar el valor anterior de la fila de esta nueva columna
DT[(i-1), 4]fuente