2013-03-22 23 views
6

Facendo una fusione tra un data.table popolata e un altro che è introduce una riga vuota NA nel data.table risultante:merge.data.table con all = True introduce la riga NA. È corretto?

a = data.table(c=c(1,2),key='c') 
b = data.table(c=3,key='c') 
b=b[c!=3] 
b 
# Empty data.table (0 rows) of 1 col: c 
merge(a,b,all=T) 
#  c 
# 1: NA 
# 2: 1 
# 3: 2 

Perché? Mi aspettavo che sarebbe tornato solo le righe di data.table a, come fa con merge.data.frame:

> merge.data.frame(a,b,all=T,by='c') 
# c 
#1 1 
#2 2 
+0

Quindi si desidera unire 'a' con una tabella di dati vuota' b'. Perché introduci 'b' in un modo così insolito? Perché non usare 'b = data.table()'? – user974514

+0

@ user974514: Volevo solo riprodurre il problema come appariva nel mio codice. Generalmente i 'data.table' nel mio codice sono popolati, ma a volte no, e nel mio caso le tabelle sono codificate e l'unione utilizza naturalmente queste chiavi. Un semplice 'data.table()' non riproduce esattamente il problema che ho avuto. – vsalmendra

+0

@ user974514, che darebbe un valore NULL.table (0 righe e colonne) e non ci sarà alcuna colonna "chiave". Quindi, l'unione non sarebbe possibile. – Arun

risposta

5

L'esempio in questione è troppo semplice per mostrare il problema, da qui la confusione e la discussione . L'utilizzo di due colonne data.table s non è sufficiente per mostrare cosa fa merge!

Ecco un esempio migliore:

> a = data.table(P=1:2,Q=3:4,key='P') 
> b = data.table(P=2:3,R=5:6,key='P') 
> a 
    P Q 
1: 1 3 
2: 2 4 
> b 
    P R 
1: 2 5 
2: 3 6 
> merge(a,b) # correct 
    P Q R 
1: 2 4 5 
> merge(a,b,all=TRUE) # correct. 
    P Q R 
1: 1 3 NA 
2: 2 4 5 
3: 3 NA 6 
> merge(a,b[0],all=TRUE) # incorrect result when y is empty, agreed 
    P Q R 
1: NA NA NA 
2: NA NA NA 
3: 1 3 NA 
4: 2 4 NA 
> merge.data.frame(a,b[0],all=TRUE) # correct 
    P Q R 
1 1 3 NA 
2 2 4 NA 

Ricardo avuto modo di fondo di questo e fissato in v1.8.9. News:

unione non restituisce spuria row (s) NA quando y è vuota e all.y = TRUE (o tutti = TRUE), #2633. Grazie a Vinicius Almendra per aver segnalato. Test aggiunto.

0

Dato si definiscono a e b nel vostro senso. Il semplice utilizzo di rbind(a,b) restituirebbe solo le righe di a.

Tuttavia, se si desidera unire la tabella di dati NULL b con un'altra tabella di dati non vuota a, esiste un approccio diverso. Ho avuto un problema simile quando ho dovuto unire tabelle di dati diverse all'interno di loop diversi. Ho usato questa soluzione alternativa.

#some loop that returns data.table named a 
    #another loop starts 
    if(all.equal(a,b<-data.table())==TRUE){ 
    b<-a 
    next 
    } 
    merge(a,b,c("Factor1","Factor2")) 

Questo mi ha aiutato, forse aiuterà anche te.

+0

Scusate, non ho proprio capito la vostra if-statement. Se 'a' è un' data.table' di dimensioni '0 per 0' (come' b'), allora assegni 'b' a' a'. Perché? E non stai usando 'copy (a)'. Questo assegnerà solo per riferimento e non copierà a a b. Non capisco – Arun

+0

Supponiamo di avere un ciclo in cui si compila data.table 'a'. Quindi non è vuoto. Ma alla fine del ciclo, vuoi unirlo con un'altra tabella di dati 'b' che può essere vuota nella prima iterazione, ma diventa non vuota al secondo. Questo è ciò che risolve questa soluzione. – user974514

+0

Il voto negativo viene da me, se potessi spiegare (o modificare), sarei felice di alzare la voce). – Arun

1

tutto: logico; all = TRUE è una scorciatoia per salvare entrambe le impostazioni all.x = TRUE e all.y = TRUE.

all.x: logico; se TRUE, le righe aggiuntive verranno aggiunte all'output, una per ogni riga in x che non ha una riga corrispondente in y. Queste righe avranno "NA in quelle colonne che di solito sono riempite con valori da y. L'impostazione predefinita è FALSE, pertanto nell'output sono incluse solo le righe con i dati di x e y.

all.y: logico; analogo a tutto.x sopra.

questo è preso da data.table documentation. Per ulteriori informazioni, consulta la descrizione degli argomenti per la funzione merge.

Penso che questo risponda alla tua domanda.

+0

forse potresti provare 'ifelse (dim (b) [1] == 0, unione (a, b, all.x = T), unione (a, b, all.y = T))' o qualcosa di simile –

+1

Questa documentazione è la stessa di "merge.data.frame', che si comporta diversamente. Non capisco perché un join esterno completo con una tabella vuota debba aggiungere una riga NA. – vsalmendra

0

Questo è da aspettarselo, come per merge.data.frameall=T è un full outer join, in modo da ottenere tutte le chiavi di entrambe le tabelle vedono about merge

+0

La tabella 'b' ha una chiave vuota (nessuna riga), che è diversa da una chiave con valore NA. – vsalmendra

+2

Potresti aver trovato un bug, perché questo è un caso molto insolito, puoi pubblicare su un elenco di tabelle di dati? – statquant

+0

Grazie. L'ho appena presentato e ho trovato un altro bug, anch'esso relativo al dato vuoto di data.table ... – vsalmendra