2016-08-28 1 views
7

Gestern habe ich diese Antwort gegeben: Matching Data Tables by five columns to change a value in another column.Ist es möglich, das data.table index-join-assignment-Idiom zu verwenden, um einen linken Join auszuführen und NAs in den nicht übereinstimmenden Zeilen von i an x ​​zuzuweisen?

In den Kommentaren fragte das OP, ob wir effektiv einen linken Join der beiden Tabellen erreichen und dadurch die NAs erhalten könnten, die dazu führen würden, dass die rechte Tabelle der linken Tabelle zugewiesen würde. Es scheint mir, dass data.table keine Möglichkeit bietet, dies zu tun.

Hier ist das Beispiel Fall, dass ich in dieser Frage verwendet:

set.seed(1L); 
dt1 <- data.table(id=1:12,expand.grid(V1=1:3,V2=1:4),blah1=rnorm(12L)); 
dt2 <- data.table(id=13:18,expand.grid(V1=1:2,V2=1:3),blah2=rnorm(6L)); 
dt1; 
##  id V1 V2  blah1 
## 1: 1 1 1 -0.6264538 
## 2: 2 2 1 0.1836433 
## 3: 3 3 1 -0.8356286 
## 4: 4 1 2 1.5952808 
## 5: 5 2 2 0.3295078 
## 6: 6 3 2 -0.8204684 
## 7: 7 1 3 0.4874291 
## 8: 8 2 3 0.7383247 
## 9: 9 3 3 0.5757814 
## 10: 10 1 4 -0.3053884 
## 11: 11 2 4 1.5117812 
## 12: 12 3 4 0.3898432 
dt2; 
## id V1 V2  blah2 
## 1: 13 1 1 -0.62124058 
## 2: 14 2 1 -2.21469989 
## 3: 15 1 2 1.12493092 
## 4: 16 2 2 -0.04493361 
## 5: 17 1 3 -0.01619026 
## 6: 18 2 3 0.94383621 
key <- paste0('V',1:2); 

Und hier ist die Lösung, die ich gab die nicht NAs bekommt für nicht-passende Zeilen:

dt1[dt2,on=key,id:=i.id]; 
dt1; 
##  id V1 V2  blah1 
## 1: 13 1 1 -0.6264538 
## 2: 14 2 1 0.1836433 
## 3: 3 3 1 -0.8356286 
## 4: 15 1 2 1.5952808 
## 5: 16 2 2 0.3295078 
## 6: 6 3 2 -0.8204684 
## 7: 17 1 3 0.4874291 
## 8: 18 2 3 0.7383247 
## 9: 9 3 3 0.5757814 
## 10: 10 1 4 -0.3053884 
## 11: 11 2 4 1.5117812 
## 12: 12 3 4 0.3898432 

Was wir brauchen, ist für die id Werte 12 und darunter, die in dt1 bleiben, ersetzt durch NA (nicht weil sie 12 und darunter sind, und nicht weil diese ID-Werte werden aus dt2 fehlen, sondern weil die auf den key Spalten verbinden, nämlich V1 und V2, führt nicht für die Zeilen in dt1 gegen dt2 in einem Spiel).

Wie ich in den Kommentaren zu dieser Frage sagte, ist eine Problemumgehung, dt1$id allen NAs vorherzuassignieren und dann die Index-Join-Zuweisung auszuführen. Daher ist dies die erwartete Ausgabe:

dt1$id <- NA; 
dt1[dt2,on=key,id:=i.id]; 
dt1; 
##  id V1 V2  blah1 
## 1: 13 1 1 -0.6264538 
## 2: 14 2 1 0.1836433 
## 3: NA 3 1 -0.8356286 
## 4: 15 1 2 1.5952808 
## 5: 16 2 2 0.3295078 
## 6: NA 3 2 -0.8204684 
## 7: 17 1 3 0.4874291 
## 8: 18 2 3 0.7383247 
## 9: NA 3 3 0.5757814 
## 10: NA 1 4 -0.3053884 
## 11: NA 2 4 1.5117812 
## 12: NA 3 4 0.3898432 

Ich denke, das Problem zu umgehen ist ok, aber ich bin nicht sicher, warum data.table nicht mit einem in einem Schuss der Lage, diese Funktionalität zu sein scheint Index-Join -Betrieb zuweisen. Im Folgenden sind drei Sackgassen Ich erforschte:

1:nomatch

data.table ein nomatch Argument liefert, die wie die all, all.x und all.y Argumente von merge() ein wenig aussieht. Dies ist eigentlich ein sehr begrenztes Argument; es erlaubt nur den Wechsel von einem rechten Join (nomatch=NA, der Standard) zu einem inneren Join (nomatch=0). Wir können keine linke Verbindung damit erreichen.

2: Flip dt1 und dt2

Seit dt1[dt2] ist ein Recht kommen, wir können es nur umdrehen, was bedeutet, dt2[dt1], an den entsprechenden linken zu erreichen.

Das wird nicht funktionieren, weil wir brauchen die := in-Place-Zuordnung Syntax im j Argumente verwenden, um in dt1 zuweisen und unter dem blätterte Anruf, werden wir stattdessen dt2 werden zuweisen. Ich versuchte, i.id unter dem umgedrehten Befehl zuzuweisen, aber es beeinflusste nicht das ursprüngliche dt1.

3: Verwendung merge.data.table()

Wir merge.data.table() mit dem all.x=T Argument nennen kann mitmachen links zu erreichen. Das Problem ist jetzt, dass merge.data.table() kein j Argument hat, und es bietet einfach keine Möglichkeit, eine Spalte der linken (oder rechten) Tabelle in-place zuzuordnen.


Also, ist es möglich, diese Operation überhaupt mit data.table durchzuführen? Und wenn ja, wie kann man das am besten machen?

Antwort

8

AFAIU möchten Sie nur id Spalte von dt2 bis dt1 suchen. Original id Variable in dt1 scheint nicht mit dem gesamten Prozess verbunden sein, wie Sie auf V1,V2 beitreten, und Sie wollen nicht dt1$id Werte im Ergebnis haben. Der technisch korrekte Weg ist es, diese Spalte überhaupt nicht zu verwenden.

set.seed(1) 
library(data.table) 
dt1 <- data.table(id=1:12,expand.grid(V1=1:3,V2=1:4),blah1=rnorm(12L)); 
dt2 <- data.table(id=13:18,expand.grid(V1=1:2,V2=1:3),blah2=rnorm(6L)); 
on = paste0("V",1:2) # I rename to `on` to not mask `key` function 
dt1[,id:=NULL 
    ][dt2,on=on,id:=i.id 
     ][] 
# V1 V2  blah1 id 
# 1: 1 1 -0.6264538 13 
# 2: 2 1 0.1836433 14 
# 3: 3 1 -0.8356286 NA 
# 4: 1 2 1.5952808 15 
# 5: 2 2 0.3295078 16 
# 6: 3 2 -0.8204684 NA 
# 7: 1 3 0.4874291 17 
# 8: 2 3 0.7383247 18 
# 9: 3 3 0.5757814 NA 
#10: 1 4 -0.3053884 NA 
#11: 2 4 1.5117812 NA 
#12: 3 4 0.3898432 NA 

Abgesehen von der Frage ...
- Sie haben nicht ; am Ende der Leitung zu verwenden, wenn nur einzelne Ausdruck
zu bewerten - dt1[, id := NA_integer_] anstelle von dt1$id <- NA
- Verwenden Sie set.seed bei der Bereitstellung von Code mit rnorm und andere Zufälligkeit bezogene Aufrufe

+1

Minor: Wenn Sie die Reihenfolge der Spalte beibehalten möchten ved, benutze 'id: = NA' anstelle von 'id: = NULL'. – Arun

+1

Ausgezeichnete Antwort. Es ist mir nie in den Sinn gekommen, dass die ursprüngliche "id" -Spalte in "dt1" für die Konstruktion der neuen "id" -Spalte irrelevant ist. Ich nehme an, dass es keinen Vorteil für die Verwendung eines linken Joins mit dem Index-Join-Zuweisungs-Idiom geben kann, da nicht übereinstimmende Zeilen entweder alleine gelassen werden sollten (erreichbar mit einem inneren/rechten Join) oder ihre Ersatzwerte sein können unabhängig von den vorherigen Werten bestimmt, was durch vollständiges Wiederherstellen der Spalte (was zu NAs führt) oder Zuweisen des gewünschten Ersatzwerts vor der Index-Join-Zuweisungsoperation erreichbar ist. – bgoldst

Verwandte Themen