2014-04-15 1 views
18

Sto cercando di capire la logica di J() ricerca quando ci sei chiavi duplicate in un data.table in R.Perché è richiesto allow.cartesian quando si uniscono dati.tables con chiavi duplicate?

Ecco un piccolo esperimento ho provato:

library(data.table) 
options(stringsAsFactors = FALSE) 

x <- data.table(keyVar = c("a", "b", "c", "c"), 
      value = c( 1, 2, 3, 4)) 
setkey(x, keyVar) 

y1 <- data.frame(name = c("d", "c", "a")) 
x[J(y1$name), ] 
## OK 

y2 <- data.frame(name = c("d", "c", "a", "b")) 
x[J(y2$name), ] 
## Error: see below 

x2 <- data.table(keyVar = c("a", "b", "c"), 
       value = c( 1, 2, 3)) 
setkey(x2, keyVar) 
x2[J(y2$name), ] 
## OK 

Il messaggio di errore Sto ottenendo è:

Error in vecseq(f__, len__, if (allow.cartesian) NULL else as.integer(max(nrow(x), : 
Join results in 5 rows; more than 4 = max(nrow(x),nrow(i)). Check for duplicate key 
values in i, each of which join to the same group in x over and over again. If that's 
ok, try including `j` and dropping `by` (by-without-by) so that j runs for each group 
to avoid the large allocation. If you are sure you wish to proceed, rerun with 
allow.cartesian=TRUE. Otherwise, please search for this error message in the FAQ, Wiki, 
Stack Overflow and datatable-help for advice. 

Non lo capisco davvero. So che dovrei evitare chiavi duplicate in una funzione di ricerca, voglio solo ottenere alcune informazioni quindi non farò alcun errore in futuro.

Grazie mille per l'aiuto. Questo è un grande strumento.

+3

'allow.cartesian' è stato implementato dopo che ho fatto qualcosa di stupido quando ho iniziato a utilizzare data.table: http://stackoverflow.com/q/11610562/1412059 – Roland

risposta

23

Non è necessario evitare chiavi duplicate. Finché il risultato non diventa più grande di max(nrow(x), nrow(i)), non avrai questo errore, anche se hai duplicati. È fondamentalmente una misura precauzionale.

Quando si duplicano le chiavi, il join risultante può talvolta diventare molto più grande. Dal momento che data.table conosce il numero totale di righe risultanti da questo join abbastanza presto, fornisce questo messaggio di errore e chiede all'utente di utilizzare l'argomento allow.cartesian=TRUE se ne è veramente sicuro.

Ecco un (esagerato) esempio che illustra l'idea alla base di questo messaggio di errore:

require(data.table) 
DT1 <- data.table(x=rep(letters[1:2], c(1e2, 1e7)), 
        y=1L, key="x") 
DT2 <- data.table(x=rep("b", 3), key="x") 

# not run 
# DT1[DT2] ## error 

dim(DT1[DT2, allow.cartesian=TRUE]) 
# [1] 30000000  2 

I duplicati in DT2 provocato 3 volte il numero totale di "a" in DT1 (= 1E7). Immagina di aver eseguito il join con i valori 1e4 in DT2, i risultati sarebbero esplosi! Per evitare questo, c'è l'argomento allow.cartesian che per impostazione predefinita è FALSE.

Detto questo, penso che Matt abbia detto una volta che è possibile fornire l'errore solo in caso di join "grandi" (o join che si traducono in un numero enorme di righe - che potrebbero essere impostate arbitrariamente, credo). Questo, quando implementato/implementerà correttamente il join senza questo messaggio di errore in caso di join che non esplodono in modo combinatorio.

+1

Grazie Arun, ora ha senso. – yuez

+1

Non ho ascoltato questo avvertimento e ho finito di passare da una tabella con le voci 1e5 a una tabella con 1e10 voci che avrebbero occupato 100 GB + di spazio RAM e si sarebbero schiantati sul mio server. Ahia. – user5359531

0

+1 a quello che ha detto Arun. Personalmente ho usato dplyr per cose del genere per molto tempo, e un semplice errore di battitura (ad esempio, in un nome di colonna in uno dei frame di dati) durante un join potrebbe provocare una moltiplicazione cartesiana con un risultato enorme. Dplyr inizia appena a farlo senza realmente verificare se avrà abbastanza memoria almeno, a quel punto il mio computer si è completamente bloccato e tutti i progressi sono andati persi. Questa misura di sicurezza in data.table è stata creata per impedirlo.

+3

Questo non fornisce una risposta alla domanda, ma dovrebbe piuttosto essere un commento sotto la risposta di Arun. – Cleb