在data.table中使用rep添加多列

时间:2018-06-25 09:14:23

标签: r data.table rep

我正在尝试使用rep函数创建固定数量的列(在本例中为4列)。在B列中提到在这些列中应多久重复数字1。其余的列应填充0。

但是我收到错误消息

  

“ rep(1,B)中的错误:无效的'times'参数”

而且不知道如何解决

test <- data.table(A = c("XYZ", "ZYX", "WER"),
                   B = c(1, 3, 2))
cols <- LETTERS[3:6] 
test[, (cols) := c(rep(1, B), rep(0, length(cols) - B))]  

#result should be 
result <- data.table(A = c("XYZ", "ZYX", "WER"),
                     B = c(1, 3, 2),
                     C = c(1, 1, 1),
                     D = c(0, 1, 1),
                     E = c(0, 1, 0),
                     F = c(0, 0, 0))

1 个答案:

答案 0 :(得分:4)

这使用了一些非“ data.table”逻辑,但仍然应该很快:

test[, (cols) := {
  D <- diag(length(cols))
  D[lower.tri(D)] <- 1
  data.table(D[B,])
}]

#     A B C D E F
#1: XYZ 1 1 0 0 0
#2: ZYX 3 1 1 1 0
#3: WER 2 1 1 0 0

之所以起作用,是因为它创建了一个具有对角线和下三角填充的矩阵,然后使用test$B对该矩阵的行进行子集化。

或者,您可以遍历要分配的列的长度序列,并检查值是否等于或小于:

test[, (cols) := lapply(1:length(cols), function(x) as.numeric(x <= B))]

一些比较时机,增加了24列和3M行:

cols <- LETTERS[-(1:2)]
test <- test[rep(1:3,1e6),]

system.time(test[, (cols) := {
  D <- diag(length(cols))
  D[lower.tri(D)] <- 1
  data.table(D[B,])
}])

#   user  system elapsed 
#  0.937   0.651   1.591 

第二次失败了:

system.time(
  test[, (cols) := lapply(1:length(cols), function(x) as.numeric(x <= B))]
)
#   user  system elapsed 
#  0.313   0.132   0.446