我正在将数字列表转换为矩阵。数字列表是编码文本。每个单词都有一个与之关联的数字,如'the':1,'it':2等。我想得到一个值矩阵,其中编码单词的存在由'1'表示。因此,如果我们的编码文本之一看起来像:
c(1, 4, 2)
然后相应的矩阵(最大单词索引为10)看起来像:
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 1 1 0 1 0 0 0 0 0 0
所以这就是我目前的方式:
encoded.text <- list(c(1, 3, 2), c(1, 7, 8))
result <- matrix(0, nrow = length(encoded.text), ncol = 10)
for (i in 1:length(encoded.text)) {
result[i, encoded.text[[i]]] <- 1
}
我想知道,有没有比for循环更好/更有效的方法呢?
这是row/column
索引的一个选项。我们unlist
为列索引的'encoded.text',而rep
licate list
的序列与lengths
的list
作为row
索引。 cbind
它创建一个行/列索引矩阵,根据索引提取'结果'的值并将其分配给1
m1 <- cbind(rep(seq_along(encoded.text), lengths(encoded.text)),
unlist(encoded.text))
result[m1] <- 1
result
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
#[1,] 1 1 1 0 0 0 0 0 0 0
#[2,] 1 0 0 0 0 0 1 1 0 0
注意:apply/Map
等只是for
循环的循环。除了添加答案之外,它不会给出任何性能增量
n <- 1e6
test <- rep(encoded.text, n)
testresult <- matrix(0, nrow = length(test), ncol = 10)
testresult2 <- copy(testresult)
testresult3 <- copy(testresult)
system.time({
m2 <- cbind(rep(seq_along(test), lengths(test)),
unlist(test))
testresult[m2] <- 1
})
# user system elapsed
# 0.290 0.098 0.388
system.time({
testresult2[do.call(rbind, Map(cbind, seq_len(length(test)), test))] <- 1
})
# user system elapsed
# 8.383 0.462 8.787
system.time({
for (i in 1:length(test)) {
testresult3[i, test[[i]]] <- 1
}
})
# user system elapsed
# 0.648 0.131 0.778
如果我们增加'n'并再次重新运行(在构建数据之后)
n <- 1e7
system.time({
m2 <- cbind(rep(seq_along(test), lengths(test)),
unlist(test))
testresult[m2] <- 1
})
# user system elapsed
# 2.699 1.225 3.990 # almost 2 times efficient now
system.time({
testresult2[do.call(rbind, Map(cbind, seq_len(length(test)), test))] <- 1
})
# user system elapsed
# 88.584 5.047 94.384
system.time({
for (i in 1:length(test)) {
testresult3[i, test[[i]]] <- 1
}
})
# user system elapsed
# 5.734 0.742 6.461
- n <- 1e7
的微观标记构建数据
ak <- function() {
m2 <- cbind(rep(seq_along(test), lengths(test)),
unlist(test))
testresult[m2] <- 1
}
wfw <- function() {
for (i in 1:length(test)) {
testresult3[i, test[[i]]] <- 1
}
}
library(microbemchmark)
microbenchmark(ak(), wfw(), unit = 'relative', times = 20L)
#Unit: relative
# expr min lq mean median uq max neval cld
# ak() 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 20 a
# wfw() 1.946415 1.945528 1.927263 1.926645 1.910907 1.940207 20 b
我们可以创建一个行和列值的矩阵,我们希望使用mapply
放置1
result[do.call(rbind, Map(cbind, seq_len(length(encoded.text)), encoded.text))] <- 1
result
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
#[1,] 1 1 1 0 0 0 0 0 0 0
#[2,] 1 0 0 0 0 0 1 1 0 0