2013-02-06 8 views
14

Ich habe zwei Datentabellen, DT1 und DT2:Update-Untergruppe von data.table basierend auf beitreten

set.seed(1) 
DT1<-data.table(id1=rep(1:3,2),id2=sample(letters,6), v1=rnorm(6), key="id2") 
DT1 
## id1 id2   v1 
## 1: 2 e 0.7383247 
## 2: 1 g 1.5952808 
## 3: 2 j 0.3295078 
## 4: 3 n -0.8204684 
## 5: 3 s 0.5757814 
## 6: 1 u 0.4874291 

DT2<-data.table(id2=c("n","u"), v1=0, key="id2") 
DT2 
## id2 v1 
## 1: n 0 
## 2: u 0 

Ich würde DT1 aktualisieren möchten basiert auf einem System mit DT2 beitreten, aber nur für eine Teilmenge von DT1. Zum Beispiel für DT1[id1==3], würde ich den Wert von v1 in Zeile 4 erwarten, wie im folgende Ergebnis aktualisiert werden:

DT1 
## id1 id2   v1 
## 1: 2 e 0.7383247 
## 2: 1 g 1.5952808 
## 3: 2 j 0.3295078 
## 4: 3 n   0 
## 5: 3 s 0.5757814 
## 6: 1 u 0.4874291 

Ich weiß, wie eine Tabelle zu aktualisieren (mit dem := Zuweisungsoperator), wie beitreten die Tabellen (DT1[DT2]) und wie Sie eine Tabelle unterteilen (DT1[id1==3]). Ich bin mir jedoch nicht sicher, wie ich alle drei auf einmal machen soll.

BEARBEITEN Sie: Beachten Sie, dass das ursprüngliche Beispiel nur versucht, eine Spalte zu aktualisieren, aber meine tatsächlichen Daten erfordert Aktualisierung vieler Spalten. Betrachten Sie die zusätzlichen Szenarien in DT1b und DT2b:

set.seed(2) 
DT1b<-DT1[,v2:=rnorm(6)] # Copy DT1 and add a new column 
setkey(DT1b,id2) 
DT1b 
## id1 id2   v1   v2 
## 1: 2 e 0.7383247 -0.89691455 
## 2: 1 g 1.5952808 0.18484918 
## 3: 2 j 0.3295078 1.58784533 
## 4: 3 n -0.8204684 -1.13037567 
## 5: 3 s 0.5757814 -0.08025176 
## 6: 1 u 0.4874291 0.13242028 

DT2b<-rbindlist(list(DT2,data.table(id2="e",v1=0))) # Copy DT2 and add a new row 
DT2b[,v2:=-1] # Add a new column to DT2b 
setkey(DT2b,id2) 
DT2b 
## id2 v1 v2 
## 1: e 0 -1 
## 2: n 0 -1 
## 3: u 0 -1 

Basierend auf den hilfreichen Antworten von @nmel und @BlueMagister, kam ich mit dieser Lösung für das aktualisierte Szenario:

DT1b[DT2b[DT1b[id1 %in% c(1,2)],nomatch=0],c("v1","v2"):=list(i.v1,i.v2)] 
DT1b 
## id1 id2   v1   v2 
## 1: 2 e 0.0000000 -1.00000000 
## 2: 1 g 1.5952808 0.18484918 
## 3: 2 j 0.3295078 1.58784533 
## 4: 3 n -0.8204684 -1.13037567 
## 5: 3 s 0.5757814 -0.08025176 
## 6: 1 u 0.0000000 -1.00000000 

Antwort

13

Der einfachste Weg, ich kann sich vorstellen, zu Schlüssel durch id1 auch zu sein. zB

setkey(DT1, id2,id1) 
DT2[, id1 := 3] 
setkey(DT2, id2, id1) 

# use i.v1 to reference v1 from the i component 
DT1[DT2, v1 := i.v1 ] 


DT1 
    id1 id2  v1 
1: 2 e 0.7383247 
2: 1 g 1.5952808 
3: 2 j 0.3295078 
4: 3 n 0.0000000 
5: 3 s 0.5757814 
6: 1 u 0.4874291 
+0

Vielen Dank für Ihre Antwort und andere Kommentare, @Mnel. Dieser Ansatz funktioniert für das ursprüngliche Beispiel und kann problemlos für den Fall erweitert werden, dass mehrere Spalten aktualisiert werden müssen und nicht nur eine Spalte. Aber wenn die Teilmenge komplizierter ist (z.B. "id1 == 3 | id1 == 2"; siehe die aktualisierte Frage), scheint es, dass das Hinzufügen des id1-Schlüssels zu DT2 komplizierter wird. – dnlbrky

7

Dies ist ähnlich mnel ‚s solution sondern nutzt ifelse anstelle eines zweiten Schlüssels.

DT1[DT2, v1 := ifelse(id1==3, i.v1, v1),nomatch=0] 
+0

Danke für deine Antwort, @BlueMagister. Dies funktioniert definitiv für das Beispiel. Wie würden Sie Ihre Antwort ändern, wenn die Tabellen viele Spalten aktualisieren müssten, anstatt nur eine? Erweitern Sie es auf zwei Spalten, ich denke, der mittlere Teil Ihrer Lösung wäre etwas wie 'c (" v1 "," v2 "): = Liste (ifelse (id1 == 3, i.v1, v1), ifelse (id1 == 3, i.v2, v2)). – dnlbrky

+2

@ dnlbrky, das Problem mit den multiplen ifelse-Anweisungen ist, dass Sie 'id1 == 3' und 'ifelse' mehrere Male auswerten müssen. Wenn Sie Subset als Teil der Keying (eine binäre Suche) wird es viel effizienter. – mnel

+0

Ja, @Mnel, ich hätte ausdrücklich sagen sollen, dass mein Versuch, die Lösung von @BlueMagister zu erweitern, nicht effizient war und dass ich nach etwas Besserem als meinem Versuch fischerte. Ich mag es, dass dieser Ansatz von @BlueMagister flexibel ist, indem er der Teilmenge weitere Bedingungen hinzufügt (z. B. "id1 == 3 | id == 2"). Ich habe meine Frage aktualisiert, um das Szenario mit mehreren Spalten und mehreren Teilmengen zu berücksichtigen. – dnlbrky

Verwandte Themen