Здесь используется немного логики, отличной от '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