2016-04-01 16 views
2

Ich habe zwei data.table mit der gleichen Struktur. Zwei Schlüsselspalten gefolgt von mehreren Datenspalten. Die Anzahl der Datenspalten kann variieren. Ich möchte die Werte aus der zweiten data.table zu den entsprechenden Zeilen/Spalten in der ersten data.table hinzufügen.r data.table Update mehrere Spalten in Join

DT1 <- cbind(data.table(loc=c("L1","L2","L3"), product=c("P1","P2","P1")), matrix(10,nrow=3,ncol=12)) 
setkey(DT1, loc, product) 
DT1 
    loc product V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 
1: L1  P1 10 10 10 10 10 10 10 10 10 10 10 10 
2: L2  P2 10 10 10 10 10 10 10 10 10 10 10 10 
3: L3  P1 10 10 10 10 10 10 10 10 10 10 10 10 
DT2 <- cbind(data.table(loc=c("L2","L3"), product=c("P2","P1")), matrix(1:24,nrow=2,ncol=12)) 
setkey(DT2, loc, product) 
    loc product V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 
1: L2  P2 1 3 5 7 9 11 13 15 17 19 21 23 
2: L3  P1 2 4 6 8 10 12 14 16 18 20 22 24 

Meine beste Wette ist, so weit das folgende

DT1[DT2, 3:14 := as.data.table(DT1[DT2, 3:14, with=FALSE] + DT2[, 3:14, with=FALSE]), with=FALSE] 
    loc product V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 
1: L1  P1 10 10 10 10 10 10 10 10 10 10 10 10 
2: L2  P2 11 13 15 17 19 21 23 25 27 29 31 33 
3: L3  P1 12 14 16 18 20 22 24 26 28 30 32 34 

Beachten Sie, dass nRow und ncol und die Lok und Produkteinträge sind alle Variablen auf den Quelldaten abhängig.

Dies funktioniert, wenn jede Zeile in DT2 mit einer in DT1 übereinstimmt, aber ansonsten zu unerwarteten Ergebnissen führt. Gibt es eine rigorosere/elegantere Art, die RHS auszudrücken, um diese variable Anzahl von Spaltenzuweisungen zu machen, die sowohl DT1 als auch DT2 betreffen?

Antwort

0

Eine Möglichkeit ist die Verbindung zu tun, und wo Sie Spalten dupliziert haben, können Sie einen Ausdruck erstellen, diese Namen zu verwenden, um die Summe

DT3 <- DT2[ DT1 ] 

dup <- names(DT3)[grep("[i.]", names(DT3))] 
dup2 <- gsub("[i.]", "", dup) 
expr <- paste0("`:=`(", paste0(dup2, "=", dup2, "+", dup, collapse = ","), ")") 

## set NA to 0 
for(j in names(DT3)) set(DT3, which(is.na(DT3[[j]])), j, 0) 

DT3[, eval(parse(text = expr))][, c("loc", "product", dup2), with=F] 

# loc product V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 
# 1: L1  P1 10 10 10 10 10 10 10 10 10 10 10 10 
# 2: L2  P2 11 13 15 17 19 21 23 25 27 29 31 33 
# 3: L3  P1 12 14 16 18 20 22 24 26 28 30 32 34 
5

Wie wäre es auszuführen:

cols = paste0('V', 1:12) 

DT1[DT2, (cols) := setDT(mget(cols)) + mget(paste0('i.', cols))] 
DT1 
# loc product V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 
#1: L1  P1 10 10 10 10 10 10 10 10 10 10 10 10 
#2: L2  P2 11 13 15 17 19 21 23 25 27 29 31 33 
#3: L3  P1 12 14 16 18 20 22 24 26 28 30 32 34 
+0

Thanks @ Eddi. Sehr elegante Lösung! Ich hatte die Funktion setDT nicht gefunden. – sch56

+0

'paste0 ('i.',' Wird nicht wirklich benötigt. Hat sich das im Laufe der Zeit in data.table geändert oder hast du es zum Verständnis benutzt? – andrasz

+0

@andrasz Ich weiß nicht, was du meinst, wenn du sagst, dass es nicht gebraucht wird Ohne das Präfix "i" addieren Sie nur Spalten aus 'DT1'. – eddi

Verwandte Themen