2015-04-15 12 views
9

Ich habe ein data.table-Objekt in R mit 9.000 Spalten. Mein Code berechnet neue Werte für alle 9.000 Spalten gleichzeitig und gibt einen Vektor von Werten zurück. Ich möchte nur die Zeile in der data.table mit allen Werten auf einmal ersetzen. In einem dataFrame-Objekt ist dies einfach. Ich kann jedoch nicht herausfinden, wie das in einer data.table funktioniert.Aktualisieren Sie eine ganze Zeile in data.table in R

d <- data.table(q=c(1,2,3,4,5,6,7,8,9), x=rep(c("a","b","c"),each=3), y=c(1,3,6), v=1:9) 
d[q==1, := c(5,5,5,5)] # FAILS 
d[q==1, ] <- c(5,5,5,5) # FAILS 

Haben Sie eine Idee, wie Sie die ganze Zeile auf effiziente Weise aktualisieren können?

Antwort

11

Sie names(d) für LHS verwenden könnte, dann as.list benutzen, um Ihre Vektor, um eine Liste zu konvertieren so data.table wird verstehen, dass es jeden Wert auf einen verschiedenen Spalte statt alle die Werte zu zuweisen müssen jede Spalte.

Sie sind auch character Vektor numeric hier (die x Spalte) Umwandlung, so data.table eine Warnung zurück, um sicherzustellen, dass Sie sich bewusst, dass sind. Diese

vec <- c(5, 5, 5, 5) 
d[q == 1L, names(d) := as.list(vec)][] 
# q x y v 
# 1: 5 5 5 5 
# 2: 2 a 3 2 
# 3: 3 a 6 3 
# 4: 4 b 1 4 
# 5: 5 b 3 5 
# 6: 6 b 6 6 
# 7: 7 c 1 7 
# 8: 8 c 3 8 
# 9: 9 c 6 9 
0

kann auch durchgeführt werden unter Verwendung von set, für das obige Beispiel (Referenzierung von Zeilennummer).

set(d, 1L, names(d), as.list(vec)) 

Sie kann einige Geschwindigkeit gewinnen set stattdessen verwenden, aber einige der Vorteil verlieren, wenn Sie zuerst die Zeilennummern abrufen müssen.

# Create large data table 
DT = data.table(col1 = 1:1e5) 
cols = paste0('col', 1:9e3) 
for (col in cols){ DT[, col := 1:1e5, with = F] } 
vec <- rep(5,9e3) 

# Test options 
microbenchmark(
    row_idnx <- DT[,.I[col1 == 1L]], # Retrieve row number 
    set(DT, row_idnx, names(DT), as.list(vec)), 
    DT[col1 == 1L, names(DT) := as.list(vec)] 
) 

Unit: microseconds 
              expr  min  lq  mean median  uq  max neval 
       row_idnx <- DT[, .I[col1 == 1L]] 1255.430 1969.5630 2168.9744 2129.2635 2302.1000 3269.947 100 
    set(DT, row_idnx, names(DT), as.list(vec)) 171.606 207.3235 323.7642 236.6765 274.6515 7725.120 100 
DT[col1 == 1L, `:=`(names(DT), as.list(vec))] 2761.289 2998.3750 3361.7842 3155.8165 3444.6310 13473.081 100