使用行、列索引的矩阵中的索引值

Index values from a matrix using row, col indices

提问人:Mike T 提问时间:8/3/2011 最后编辑:HenrikMike T 更新时间:9/5/2020 访问量:23484

问:

我有一个 500 行× 335 列的 2D 矩阵,以及一个 120425 行的 data.frame。data.frame 有两列 和 ,它们是整数,用于索引行,列 from 。我想将 中的值添加到 的行中。matdatdatIJmatmatdat

这是我的概念失败:

> dat$matval <- mat[dat$I, dat$J]
Error: cannot allocate vector of length 1617278737

(我在 Win32 上使用 R 2.13.1)。更深入地挖掘,我发现我滥用了矩阵索引,因为似乎我只得到了一个子矩阵,而不是我预期的一维值数组,即:mat

> str(mat[dat$I[1:100], dat$J[1:100]])
 int [1:100, 1:100] 20 1 1 1 20 1 1 1 1 1 ...

我期待类似.使用行、列索引来索引 2D 矩阵以获取值的正确方法是什么?int [1:100] 20 1 1 1 20 1 1 1 1 1 ...

索引 矩阵 R-FAQ

评论

0赞 Ari B. Friedman 8/3/2011
+1 表示一个有趣的问题(这就引出了另一个问题:为什么在为 N 维矩阵传递运算符 N 向量时,没有选项将行为更改为更像这样的东西?[
0赞 joran 8/3/2011
好问题 - 我稍微编辑了一下,以修复我认为是错别字(到)。如果这不是您的意思,请随时撤消...datIdat$I

答:

11赞 Tommy 8/3/2011 #1

按照 DWin 的建议,使用矩阵进行索引当然要简洁得多,但出于某种奇怪的原因,使用一维索引手动进行索引实际上会稍微快一些:

# Huge sample data
mat <- matrix(sin(1:1e7), ncol=1000)
dat <- data.frame(I=sample.int(nrow(mat), 1e7, rep=T), 
                  J=sample.int(ncol(mat), 1e7, rep=T))

system.time( x <- mat[cbind(dat$I, dat$J)] )     # 0.51 seconds
system.time( mat[dat$I + (dat$J-1L)*nrow(mat)] ) # 0.44 seconds

该器件将二维索引转换为一维索引。这是指定整数而不是双精度值的方法。这避免了一些胁迫。dat$I + (dat$J-1L)*nrow(m)1L

...我还尝试了 gsk3 的基于应用的解决方案。不过,它的速度几乎慢了 500 倍:

system.time( apply( dat, 1, function(x,mat) mat[ x[1], x[2] ], mat=mat ) ) # 212
1赞 Ari B. Friedman 8/3/2011 #2

下面是使用 的 基于行的操作的单行代码apply

> dat <- as.data.frame(matrix(rep(seq(4),4),ncol=2))
> colnames(dat) <- c('I','J')
> dat
   I  J
1  1  1
2  2  2
3  3  3
4  4  4
5  1  1
6  2  2
7  3  3
8  4  4
> mat <- matrix(seq(16),ncol=4)
> mat
     [,1] [,2] [,3] [,4]
[1,]    1    5    9   13
[2,]    2    6   10   14
[3,]    3    7   11   15
[4,]    4    8   12   16

> dat$K <- apply( dat, 1, function(x,mat) mat[ x[1], x[2] ], mat=mat )
> dat
  I J  K
1 1 1  1
2 2 2  6
3 3 3 11
4 4 4 16
5 1 1  1
6 2 2  6
7 3 3 11
8 4 4 16
43赞 IRTFM 8/3/2011 #3

几乎。需要提供给 “[” 作为两列矩阵:

dat$matval <- mat[ cbind(dat$I, dat$J) ] # should do it.

有一点需要注意:虽然这也适用于数据帧,但它们首先被强制为矩阵类,如果任何矩阵是非数字类,则整个矩阵成为“最小分母”类。

评论

1赞 Ari B. Friedman 8/3/2011
+1 表示找到 R 明确打算做事的方式 ;-)
0赞 joran 8/3/2011
那么,如果 并且是唯一的列,就足够了吗?还是需要强制矩阵?IJmat[dat]
1赞 joran 8/3/2011
似乎强制是必要的,因为数据框实际上是一个列表。所以你也可以做.as.matrix(dat)
3赞 IRTFM 8/3/2011
@gsk3:查看“参数”部分的“?[“ 在 ”...“ 下。对数组或矩阵进行寻址时,矩阵的列数必须与寻址对象的维度数相同。该帮助页面上也有一些示例。
0赞 Chase 8/3/2011
如果 data.frame 包含超出矩阵边界的 I 和 J 索引值,会发生什么情况?我很确定它会失败......我认为@Tommy的答案将返回该方案的 NA。只是要记住一些事情......
-1赞 user4614201 2/27/2015 #4
n <- 10
mat <- cor(matrix(rnorm(n*n),n,n))
ix <- matrix(NA,n*(n-1)/2,2)
k<-0
for (i in 1:(n-1)){
    for (j in (i+1):n){
    k <- k+1
    ix[k,1]<-i
    ix[k,2]<-j
    }
}
o <- rep(NA,nrow(ix))
o <- mat[ix]
out <- cbind(ix,o)

评论

3赞 Johan Karlsson 2/27/2015
一些评论会很好,并使答案更具“吸引力”。
1赞 Skizo-ozᴉʞS ツ 2/27/2015
你不能只回答一堆代码......加油。。。稍微解释一下你的答案:)