data.table
Utilizzo di chiavi e indici
Ricerca…
introduzione
Osservazioni
Le vignette ufficiali sono la migliore introduzione a questo argomento:
Chiavi contro indici
Un data.table può essere "digitato" da una sequenza di colonne, indicando le funzioni interessate che i dati sono ordinati da tali colonne. Per ottenere o impostare la chiave, utilizzare le funzioni documentate al ?key
Allo stesso modo, le funzioni possono trarre vantaggio dagli "indici" di data.table. Ogni indice e una tabella possono avere più di uno: memorizza le informazioni sull'ordine dei dati rispetto a una sequenza di colonne. Come una chiave, un indice può accelerare determinati compiti. Per ottenere o impostare indici, utilizzare le funzioni documentate in ?indices
.
Gli indici possono anche essere impostati automaticamente (attualmente solo per una singola colonna alla volta). Vedi ?datatable.optimize
per i dettagli su come funziona e su come disabilitarlo se necessario.
Verifica e aggiornamento
I valori mancanti sono consentiti in una colonna chiave.
Le chiavi e gli indici sono memorizzati come attributi e potrebbero, per errore, non corrispondere all'ordine effettivo dei dati nella tabella. Molte funzioni verificano la validità della chiave o dell'indice prima di usarlo, ma vale la pena tenerlo a mente.
Le chiavi e gli indici vengono rimossi dopo gli aggiornamenti, laddove non è ovvio che l'ordinamento sia preservato. Ad esempio, a partire da DT = data.table(a=c(1,2,4), key="a")
, se aggiorniamo come DT[2, a := 3]
, la chiave è rotta.
Miglioramento delle prestazioni per la selezione di sottoinsiemi
# 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)
)
Corrispondenza su una colonna
Dopo la prima esecuzione di un'operazione di subsetting con ==
o %in%
...
system.time(
DT[ g1 %in% 1:100]
)
# user system elapsed
# 0.12 0.03 0.16
Un indice è stato creato automaticamente per g1
. Le successive operazioni di subsetting avvengono quasi istantaneamente:
system.time(
DT[ g1 %in% 1:100]
)
# user system elapsed
# 0 0 0
Per monitorare quando viene creato o utilizzato un indice, aggiungere l'opzione verbose=TRUE
o modificare le options(datatable.verbose=TRUE)
impostazione globale options(datatable.verbose=TRUE)
.
Corrispondenza su più colonne
Attualmente, la corrispondenza su due colonne non crea automaticamente un indice:
system.time(
DT[ g1 %in% 1:100 & g2 %in% 1:100]
)
# user system elapsed
# 0.57 0.00 0.57
Rieseguire questo e rimarrà lento. Anche se aggiungiamo manualmente l'indice con setindex(DT, g1, g2)
, rimarrà lento perché questa query non è ancora ottimizzata dal pacchetto.
Fortunatamente, se possiamo enumerare le combinazioni di valori che vogliamo cercare e un indice è disponibile, possiamo equi-join rapidamente:
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
, è importante prestare attenzione al numero di combinazioni che diventano troppo grandi.