performance - Tiempo para obtener elementos individuales de los objetos data.table y data.frame
dataframe (1)
En mi trabajo utilizo varias tablas (detalles del cliente, registros de transacciones, etc.). Como algunos de ellos son muy grandes (millones de filas), recientemente data.table
paquete data.table
(gracias Matthew). Sin embargo, algunos de ellos son bastante pequeños (algunos cientos de filas y 4/5 columnas) y se llaman varias veces. Por lo tanto, comencé a pensar en la sobrecarga de [.data.table
en la recuperación de datos en lugar de establecer () el valor de ting como ya se describió claramente en ?set
, donde, independientemente del tamaño de la tabla, un elemento se establece en aproximadamente 2 microsegundos (dependiendo de la CPU) .
Sin embargo, no parece existir el equivalente de set
para obtener un valor de una data.table
conoce la fila y la columna exactas. Una especie de loopable [.data.table
.
library(data.table)
library(microbenchmark)
m = matrix(1,nrow=100000,ncol=100)
DF = as.data.frame(m)
DT = as.data.table(m) # same data used in ?set
> microbenchmark(DF[3450,1] , DT[3450, V1], times=1000) # much more overhead in DT
Unit: microseconds
expr min lq median uq max neval
DF[3450, 1] 32.745 36.166 40.5645 43.497 193.533 1000
DT[3450, V1] 788.791 803.453 813.2270 832.287 5826.982 1000
> microbenchmark(DF$V1[3450], DT[3450, 1, with=F], times=1000) # using atomic vector and
# removing part of DT overhead
Unit: microseconds
expr min lq median uq max neval
DF$V1[3450] 2.933 3.910 5.865 6.354 36.166 1000
DT[3450, 1, with = F] 297.629 303.494 305.938 309.359 1878.632 1000
> microbenchmark(DF$V1[3450], DT$V1[3450], times=1000) # using only atomic vectors
Unit: microseconds
expr min lq median uq max neval
DF$V1[3450] 2.933 2.933 3.421 3.422 40.565 1000 # DF seems still a bit faster (23%)
DT$V1[3450] 3.910 3.911 4.399 4.399 16.128 1000
El último método es, de hecho, el mejor para recuperar rápidamente un solo elemento varias veces. Sin embargo, el set
es aún más rápido.
> microbenchmark(set(DT,1L,1L,5L), times=1000)
Unit: microseconds
expr min lq median uq max neval
set(DT, 1L, 1L, 5L) 1.955 1.956 2.444 2.444 24.926 1000
la pregunta es : si podemos set
un valor en 2.444 microsegundos, ¿no sería posible obtener un valor en un período de tiempo menor (o al menos similar)? Gracias.
EDITAR: agregar dos opciones más como se sugiere:
> microbenchmark(`[.data.frame`(DT,3450,1), DT[["V1"]][3450], times=1000)
Unit: microseconds
expr min lq median uq max neval
`[.data.frame`(DT, 3450, 1) 46.428 47.895 48.383 48.872 2165.509 1000
DT[["V1"]][3450] 20.038 21.504 23.459 24.437 116.316 1000
que lamentablemente no son más rápidos que los intentos anteriores.
Gracias a @hadley tenemos la solución!
> microbenchmark(DT$V1[3450], set(DT,1L,1L,5L), .subset2(DT, "V1")[3450], times=1000, unit="us")
Unit: microseconds
expr min lq median uq max neval
DT$V1[3450] 2.566 3.208 3.208 3.528 27.582 1000
set(DT, 1L, 1L, 5L) 1.604 1.925 1.925 2.246 15.074 1000
.subset2(DT, "V1")[3450] 0.000 0.321 0.322 0.642 8.339 1000