使用行、列索引从矩阵中索引值
Posted
技术标签:
【中文标题】使用行、列索引从矩阵中索引值【英文标题】:Index values from a matrix using row, col indices 【发布时间】:2011-10-18 17:24:17 【问题描述】:我有一个 2D 矩阵 mat
有 500 行 × 335 列,还有一个 data.frame dat
有 120425 行。 data.frame dat
有两列I
和J
,它们是用于索引行的整数,列来自mat
。我想将mat
中的值添加到dat
的行中。
这是我的概念失败:
> 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 ...
我期待像int [1:100] 20 1 1 1 20 1 1 1 1 1 ...
这样的东西。使用行、列索引来索引二维矩阵以获取值的正确方法是什么?
【问题讨论】:
+1 用于一个有趣的问题(这引出了另一个问题:为什么在传递[
运算符 N 向量的 N -维矩阵?)
好问题 - 我稍微编辑了它以修复我 认为 是一个错字(datI
到 dat$I
)。如果这不是您的意思,请随时撤消...
【参考方案1】:
几乎。需要以两列矩阵的形式提供给“[”:
dat$matval <- mat[ cbind(dat$I, dat$J) ] # should do it.
有一个警告:虽然这也适用于数据帧,但它们首先被强制转换为矩阵类,如果有任何非数字,则整个矩阵将成为“最小分母”类。
【讨论】:
+1 用于发现 R 明确打算做事的方式;-) 那么如果I
和J
是唯一的列,那么只有mat[dat]
就足够了吗?还是您需要强制转换为矩阵?
似乎强制是必要的,因为数据框实际上是一个列表。所以你也可以as.matrix(dat)
。
@gsk3:查看“...”下的 ?"[" 的参数部分。寻址数组或矩阵时,矩阵的列数必须与寻址对象的维数相同。该帮助页面上还有一些示例。
如果 data.frame 包含超出矩阵边界的 I 和 J 的索引值会发生什么?我很确定它会失败......我认为@Tommy 的答案会为这种情况返回 NA。只是要记住的事情......【参考方案2】:
按照 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
【讨论】:
【参考方案3】:这是一个使用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
【讨论】:
【参考方案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)
【讨论】:
一些 cmets 会很好,让答案更“有吸引力”。 你不能只回答一堆代码......来吧......解释一下你的答案:)以上是关于使用行、列索引从矩阵中索引值的主要内容,如果未能解决你的问题,请参考以下文章
pandas读取csv数据header参数指定作为列索引的行索引列表形成复合(多层)列索引使用xs函数获取行切面数据(level参数指定行层索引列表key参数指定索引值列表)
pandas读取csv数据index_col参数指定作为行索引的数据列索引列表形成复合(多层)行索引使用reorder_levels函数改变调整行层索引各层的顺序(指定新的索引层位置值列表)
pandas读取csv数据index_col参数指定作为行索引的数据列索引列表形成复合(多层)行索引使用reorder_levels函数改变调整行层索引各层的顺序(指定新的索引层位置值列表)
pandas读取csv数据参数指定作为行索引的数据列索引列表形成复合(多层)行索引使用xs函数获取列切面数据(axis参数指定对列进行切面level参数指定列层索引名称key参数指定索引值)
pandas读取csv数据参数指定作为行索引的数据列索引列表形成复合(多层)行索引使用xs函数获取列切面数据(axis参数指定对列进行切面level参数指定列层索引名称key参数指定索引值)
pandas使用read_csv函数读取csv数据header参数指定作为列索引的行索引列表形成复合(多层)列索引使用方括号[]基于最外层列索引名称索引列数据