【问题标题】:how to populate matrix of indices with vector of values如何用值向量填充索引矩阵
【发布时间】:2014-11-19 12:34:46
【问题描述】:

我有一个矩阵 (m.idx),其中包含我想要索引的向量的位置元素。

> m.idx
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    2    3    4    5
[2,]    3    4    5    6    7
[3,]    5    6    7    8    9

假设 x 是我的向量。

x <- c(9,3,2,5,3,2,4,8,9)

我想用x的对应位置元素重新填充矩阵索引。

所以我会...

> m.pop
     [,1] [,2] [,3] [,4] [,5]
[1,]    9    3    2    5    3
[2,]    2    5    3    2    4
[3,]    3    2    4    8    9

我可以通过以下方式以一种笨拙的方式做到这一点。

> m.pop <- t(matrix(t(matrix(x[c(t(m.idx))])),ncol(m.idx),nrow(m.idx)))

> m.pop
     [,1] [,2] [,3] [,4] [,5]
[1,]    9    3    2    5    3
[2,]    2    5    3    2    4
[3,]    3    2    4    8    9

但似乎有一种更简单的方法来索引这些值。 什么是最好的(对于大型集合来说也是最快/有效的)方法?

【问题讨论】:

  • 您的矩阵有多大?我在答案中添加了一些基准。
  • 我现在正在查看 5e3 行乘以 100 列。但是当我扩大规模时,您的回答可能会很有用 - tks。用于提供基准。正如我所料,我笨拙的方法排在最后。

标签: r matrix indexing


【解决方案1】:

怎么样:

m.idx[] <- x[m.idx]
m.idx
#      [,1] [,2] [,3] [,4] [,5]
# [1,]    9    3    2    5    3
# [2,]    2    5    3    2    4
# [3,]    3    2    4    8    9

或者,如果您不想覆盖 m.idx 矩阵,您可以这样做:

m.pop <- m.idx
m.pop[] <- x[m.pop]

添加:

另一种方法,使用structure,也相当快:

structure(x[m.idx], .Dim = dim(m.idx))
#      [,1] [,2] [,3] [,4] [,5]
# [1,]    9    3    2    5    3
# [2,]    2    5    3    2    4
# [3,]    3    2    4    8    9

当应用于 Ananda Mahto 的回答中的大 m.idx 矩阵时,我机器上的时间是

fun5 <- function() structure(x[m.idx], .Dim = dim(m.idx))
microbenchmark(fun1(), fun2(), fun3(), fun4(), fun5(), times = 10)
# Unit: milliseconds
#    expr       min        lq    median        uq       max neval
#  fun1()  303.3473  307.2064  309.2275  352.5076  353.6911    10
#  fun2()  548.0928  555.3363  587.6144  593.4492  596.5611    10
#  fun3()  480.6181  487.5807  507.5960  529.9696  533.0403    10
#  fun4() 1222.6718 1231.3384 1259.8395 1269.6629 1292.2309    10
#  fun5()  401.8450  403.7216  432.7162  455.4638  487.1755    10
identical(fun1(), fun5())
# [1] TRUE

可以看到structure在速度上其实也不算太差。

【讨论】:

  • 这比我的 `dim&lt;-` 废话要好。 +1
【解决方案2】:
matrix(x[m.idx],ncol=5)

     [,1] [,2] [,3] [,4] [,5]
[1,]    9    3    2    5    3
[2,]    2    5    3    2    4
[3,]    3    2    4    8    9

【讨论】:

  • 这实际上是一个非常好的答案,因为它不会覆盖原始的m.idx 矩阵。
【解决方案3】:

也许你可以在匹配向量/矩阵后使用dim

`dim<-`(x[m.idx], dim(m.idx))
#      [,1] [,2] [,3] [,4] [,5]
# [1,]    9    3    2    5    3
# [2,]    2    5    3    2    4
# [3,]    3    2    4    8    9

x[m.idx] 为您提供您感兴趣的值:

> x[m.idx]
 [1] 9 2 3 3 5 2 2 3 4 5 2 8 3 4 9

而且,由于这应该以与原始相同的尺寸返回,因此您只需将相同的 dim 重新分配给它。


为了好玩,一些时间安排:

fun1 <- function() `dim<-`(x[m.idx], dim(m.idx))
fun2 <- function() { m.idx[] <- x[m.idx]; m.idx }
fun3 <- function() matrix(x[m.idx], ncol = ncol(m.idx))
fun4 <- function() t(matrix(t(matrix(x[c(t(m.idx))])),ncol(m.idx),nrow(m.idx)))

m.idx <- matrix(c(1, 2, 3, 4, 5, 
                  3, 4, 5, 6, 7, 
                  5, 6, 7, 8, 9), 
                nrow = 3, byrow = TRUE)
x <- c(9, 3, 2, 5, 3, 2, 4, 8, 9)

set.seed(1)
nrow = 10000  ## Adjust nrow and ncol to test different sizes
ncol = 1000
m.idx <- matrix(sample(unique(m.idx), nrow*ncol, TRUE), ncol = ncol)
library(microbenchmark)

microbenchmark(fun1(), fun2(), fun3(), fun4(), times = 10)
# Unit: milliseconds
#    expr       min        lq    median        uq       max neval
#  fun1()  388.7123  403.3614  419.5792  475.7645  553.3420    10
#  fun2()  800.5524  838.2398  872.8189  912.1007  978.1500    10
#  fun3()  694.1511  720.5165  737.9900  799.5069  876.2552    10
#  fun4() 1941.1999 2022.6578 2095.1537 2175.4864 2341.3900    10

【讨论】:

  • 可能比其他答案更有效,但是任何使用 dim&lt;- 作为函数的东西对我来说似乎有点神秘......
  • @BenBolker,我认为理查德的回答是最恰当的。
  • 但你的确实更有效率(以防万一真的有所作为……我猜这里给出的三个答案中的任何一个都足够好,以至于这一步不会 成为任何计算的瓶颈)
  • (+1) 快了 5 毫秒。 :)
  • @RichardScriven,我同意这有点荒谬,但是在几个不同的尺寸上进行测试,它几乎始终如一地快 2 倍,这可能会有所作为。
猜你喜欢
  • 2013-05-27
  • 1970-01-01
  • 1970-01-01
  • 2018-05-06
  • 2014-11-21
  • 2021-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多