更新R中data.table中的整行

时间:2015-04-15 09:33:25

标签: r data.table

我在R中有一个包含9,000列的data.table对象。我的代码一次计算所有9,000列的新值,并返回值向量。我想一下子将data.table中的行替换为所有值。在dataFrame对象中,这很容易。但是,我无法弄清楚如何在data.table中使用它。

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

知道如何有效地一次更新整行吗?

2 个答案:

答案 0 :(得分:10)

您可以将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

答案 1 :(得分:1)

对于上面的示例(通过行号引用),也可以使用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