更新: さらに優れたソリューション
マトリックス インデックスを使用すると、速度をさらに向上させることができます。for ループを使用しない、大幅に改善されたソリューションを次に示します。
all <- factor(letters)
combos <- t(combn(as.character(all), 5))
A <- match(c(t(combos)), letters)
B <- 0:(length(A)-1) %/% 5 + 1
a <- unique(as.vector(combos))
x <- matrix(0, ncol = length(a), nrow = nrow(combos),
dimnames = list(NULL, a))
x[cbind(B, A)] <- 1L
ベンチマーク
orig <- function() {
a <- unique(as.vector(combos))
x <- matrix(0, ncol = length(a), nrow = nrow(combos),
dimnames = list(NULL, a))
for (i in 1:nrow(combos)) {
x[i, combos[i, ]] <- 1
}
x
}
new <- function() {
A <- match(c(t(combos)), letters)
B <- 0:(length(A)-1) %/% 5 + 1
a <- unique(as.vector(combos))
x <- matrix(0, ncol = length(a), nrow = nrow(combos),
dimnames = list(NULL, a))
x[cbind(B, A)] <- 1L
x
}
identical(orig(), new())
# [1] TRUE
library(microbenchmark)
microbenchmark(orig(), new(), times = 20)
# Unit: milliseconds
# expr min lq median uq max neval
# orig() 476.85206 486.11091 497.48429 512.4333 579.2695 20
# new() 87.02026 91.17021 96.88463 111.6414 175.6339 20
元の答え
このような問題では、for
ループは問題なく機能し、簡単に事前に割り当てることができます。
a <- unique(as.vector(combos))
x <- matrix(0, ncol = length(a), nrow = nrow(combos),
dimnames = list(NULL, a))
for (i in 1:nrow(combos)) {
x[i, combos[i, ]] <- 1
}
head(x)
# a b c d e f g h i j k l m n o p q r s t u v w x y z
# [1,] 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
# [2,] 1 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
# [3,] 1 1 1 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
# [4,] 1 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
# [5,] 1 1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
# [6,] 1 1 1 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0