2015-04-15 45 views
9

我有一個R有9,000列的data.table對象。我的代碼一次爲所有9,000列計算新值,並返回值的向量。我想只是將data.table中的所有值同時替換。在dataFrame對象中,這很容易。但是,我無法弄清楚如何在data.table中工作。更新data.table中的整行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 

任何想法如何有效地一次更新整個行?

回答

11

你可以使用names(d)對於LHS,然後用as.list爲了您的向量轉換成一個列表,以便data.table就會明白,它需要每一個值分配不同列,而不是所有的值每個列。

您也正在將character載體轉換爲numeric此處(x列),因此data.table將返回警告以確保您知道這一點。

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

這也可以使用set進行,上述(由行號引用)的例子。

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

可以獲得使用set而不是一些速度,但失去了一些優勢,如果你需要首先檢索該行號。

# 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