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
.N
el 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..SD
ejemplo: estaba tratando de usar alapply
y obteniendo resultados extravagantes. esto es mucho más sencillo.Usando
dplyr
usted 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 540
fuente
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 NA
fuente
data.table
paquete, pero por desgracia ...shift
ha agregado una función similar llamada adata.table
partir 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 540
Y evitar el uso
seq_len
ohead
o cualquier otra función.fuente
.I
conseq_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 540
fuente
.N
está 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