2015-04-15 2 views
9

Ho un oggetto data.table in R che ha 9.000 colonne. Il mio codice calcola nuovi valori per tutte le 9.000 colonne contemporaneamente e restituisce un vettore di valori. Mi piacerebbe solo sostituire la riga nel data.table con tutti i valori in una volta. In un oggetto dataFrame è facile. Tuttavia, non riesco a capire come farlo funzionare in un data.table.Aggiornare un'intera riga 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 

Qualche idea su come aggiornare in modo efficiente l'intera riga in una sola volta?

risposta

11

Si potrebbe utilizzare names(d) per LHS, quindi utilizzare as.list al fine di convertire il vostro vettoriale in una lista in modo data.table capirà che ha bisogno di assegnare ogni valore a una colonna diversa invece tutte i valori da ciascuna colonna.

Siete anche convertendo character vettore a numeric qui (la colonna x), in modo data.table tornerà un avvertimento al fine di assicurarsi che siano consapevoli di questo.

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

Questo può anche essere fatto usando set, per l'esempio precedente (riferimento dal numero di riga).

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

È può guadagnare un po 'di velocità utilizzando set invece, ma perdere un po' del vantaggio se avete bisogno di recuperare i numeri di riga prima.

# 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