performance r dataframe data.table

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