data.table
Uso de claves e índices.
Buscar..
Introducción
Observaciones
Las viñetas oficiales son la mejor introducción a este tema:
- "Claves y subconjunto basado en búsqueda binaria rápida"
- "Índices secundarios e indexación automática"
Teclas vs índices
Una tabla de datos puede ser "codificada" por una secuencia de columnas, indicando a las funciones interesadas que los datos están ordenados por esas columnas. Para obtener o configurar la clave, use las funciones documentadas en ?key
.
De manera similar, las funciones pueden aprovechar los "índices" de una tabla de datos. Cada índice, y una tabla puede tener más de uno, almacena información sobre el orden de los datos con respecto a una secuencia de columnas. Al igual que una clave, un índice puede acelerar ciertas tareas. Para obtener o establecer índices, utilice las funciones documentadas en los ?indices
Los índices también se pueden configurar automáticamente (actualmente solo para una columna a la vez). Consulte ?datatable.optimize
para obtener detalles sobre cómo funciona esto y cómo desactivarlo si es necesario.
Verificación y actualización.
Los valores que faltan se permiten en una columna de clave.
Las claves y los índices se almacenan como atributos y pueden, por accidente, no corresponder al orden real de los datos en la tabla. Muchas funciones verifican la validez de la clave o el índice antes de usarla, pero vale la pena tenerlas en cuenta.
Las claves y los índices se eliminan después de las actualizaciones donde no es obvio que se conserva el orden de clasificación. Por ejemplo, a partir de DT = data.table(a=c(1,2,4), key="a")
, si actualizamos como DT[2, a := 3]
, la clave está rota.
Mejora del rendimiento para seleccionar subconjuntos
# example data
set.seed(1)
n = 1e7
ng = 1e4
DT = data.table(
g1 = sample(ng, n, replace=TRUE),
g2 = sample(ng, n, replace=TRUE),
v = rnorm(n)
)
Coincidencia en una columna
Después de la primera ejecución de una operación de subconjunto con ==
o %in%
...
system.time(
DT[ g1 %in% 1:100]
)
# user system elapsed
# 0.12 0.03 0.16
Se ha creado automáticamente un índice para g1
. Las siguientes operaciones de subconjunto se ejecutan casi instantáneamente:
system.time(
DT[ g1 %in% 1:100]
)
# user system elapsed
# 0 0 0
Para controlar cuándo se crea o utiliza un índice, agregue la opción verbose=TRUE
o cambie las options(datatable.verbose=TRUE)
configuración global options(datatable.verbose=TRUE)
.
Coincidencia en múltiples columnas
Actualmente, la coincidencia en dos columnas no crea automáticamente un índice:
system.time(
DT[ g1 %in% 1:100 & g2 %in% 1:100]
)
# user system elapsed
# 0.57 0.00 0.57
Vuelva a ejecutar esto y seguirá siendo lento. Incluso si agregamos manualmente el índice con setindex(DT, g1, g2)
, seguirá siendo lento porque esta consulta aún no está optimizada por el paquete.
Afortunadamente, si podemos enumerar las combinaciones de valores que queremos buscar y hay un índice disponible, podemos unirnos rápidamente:
system.time(
DT[ CJ(g1 = 1:100, g2 = 1:100, unique=TRUE), on=.(g1, g2), nomatch=0]
)
# user system elapsed
# 0.53 0.00 0.54
setindex(DT, g1, g2)
system.time(
DT[ CJ(g1 = 1:100, g2 = 1:100, unique=TRUE), on=.(g1, g2), nomatch=0]
)
# user system elapsed
# 0 0 0
Con CJ
, es importante tener cuidado con la cantidad de combinaciones que se vuelven demasiado grandes.