如何用R中的列表条目有效地设置矩阵的值?

问题描述 投票:2回答:2

我正在将数字列表转换为矩阵。数字列表是编码文本。每个单词都有一个与之关联的数字,如'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循环更好/更有效的方法呢?

r matrix sparse-matrix
2个回答
1
投票

这是row/column索引的一个选项。我们unlist为列索引的'encoded.text',而replicate list的序列与lengthslist作为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循环的循环。除了添加答案之外,它不会给出任何性能增量

Benchmarks

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

0
投票

我们可以创建一个行和列值的矩阵,我们希望使用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
© www.soinside.com 2019 - 2024. All rights reserved.