使用存储在向量中的 row/column 索引填充矩阵的最快方法
Fastest way to populate a matrix using row/column indicies stored in vectors
我正在尝试做一些看起来相对简单的事情来处理应用式的事情,但我只能使用 for 循环让它工作。
大意是我有两个向量,一个向量对应矩阵中的一行,另一个向量对应列,两者长度相同。我从一个 0 矩阵开始,然后根据两个向量中的值对递增 [行,列]。例如:
vectorCols <- c(1,2,3,1,3)
vectorRows <- c(2,1,2,3,2)
countMat <- matrix(rep(0,9),ncol=3)
最后,countMat
是:
[,1] [,2] [,3]
[1,] 0 1 0
[2,] 1 0 2
[3,] 1 0 0
使用 for
循环非常容易管理:
for (i in 1:length(vectorCols)){
countMat[vectorRows[i],vectorCols[i]] <- countMat[vectorRows[i],vectorCols[i]] + 1
}
但我不禁想到在 R 中有更好的方法来做到这一点。我试过使用 apply
函数族,但是当你想赋值时这些函数不能很好地配合某物。我知道我可以使用 mapply
并一次构建 countMat
的每个元素一个值,但这似乎效率低下——vectorRows
和 vectorCols
很长,而且看起来为 countMat
中的每个单元格完全遍历它们很浪费时间。但是除了循环和 mapply
,我想不出该怎么做。我考虑过将 assign
与 apply
系列中的一个一起使用,但有一个警告——我的矩阵实际上有列和行的名称,名称存储在 vectorCols
和 vectorRows
,似乎 assign
不想玩得很好,像 countMat["rowName"]["columnName"] (not to mention that
apply` 仍然想要 return 迭代中每个步骤的值)。
有什么建议吗?如果我没有向量列和行的名称,我也会很好奇是否有一种理想的方法来做到这一点。如果是这样的话,也许我可以将 vectorCols
和 vectorRows
转换为数字,然后构建矩阵,然后重命名所有内容。
谢谢大家。
这里有一些解决方案。不需要包。
1) table
table(vectorRows, vectorCols)
给予:
vectorCols
vectorRows 1 2 3
1 0 1 0
2 1 0 2
3 1 0 0
请注意,如果有任何行或列没有条目,则不会出现。
2) 聚合
ag <- aggregate( Freq ~ ., data.frame(Freq = 1, vectorRows, vectorCols), sum)
countMat[as.matrix(ag[-3])] <- ag[[3]]
给予:
> countMat
[,1] [,2] [,3]
[1,] 0 1 0
[2,] 1 0 2
[3,] 1 0 0
3) xtabs
xtabs(~ vectorRows + vectorCols)
给予:
vectorCols
vectorRows 1 2 3
1 0 1 0
2 1 0 2
3 1 0 0
我正在尝试做一些看起来相对简单的事情来处理应用式的事情,但我只能使用 for 循环让它工作。
大意是我有两个向量,一个向量对应矩阵中的一行,另一个向量对应列,两者长度相同。我从一个 0 矩阵开始,然后根据两个向量中的值对递增 [行,列]。例如:
vectorCols <- c(1,2,3,1,3)
vectorRows <- c(2,1,2,3,2)
countMat <- matrix(rep(0,9),ncol=3)
最后,countMat
是:
[,1] [,2] [,3]
[1,] 0 1 0
[2,] 1 0 2
[3,] 1 0 0
使用 for
循环非常容易管理:
for (i in 1:length(vectorCols)){
countMat[vectorRows[i],vectorCols[i]] <- countMat[vectorRows[i],vectorCols[i]] + 1
}
但我不禁想到在 R 中有更好的方法来做到这一点。我试过使用 apply
函数族,但是当你想赋值时这些函数不能很好地配合某物。我知道我可以使用 mapply
并一次构建 countMat
的每个元素一个值,但这似乎效率低下——vectorRows
和 vectorCols
很长,而且看起来为 countMat
中的每个单元格完全遍历它们很浪费时间。但是除了循环和 mapply
,我想不出该怎么做。我考虑过将 assign
与 apply
系列中的一个一起使用,但有一个警告——我的矩阵实际上有列和行的名称,名称存储在 vectorCols
和 vectorRows
,似乎 assign
不想玩得很好,像 countMat["rowName"]["columnName"] (not to mention that
apply` 仍然想要 return 迭代中每个步骤的值)。
有什么建议吗?如果我没有向量列和行的名称,我也会很好奇是否有一种理想的方法来做到这一点。如果是这样的话,也许我可以将 vectorCols
和 vectorRows
转换为数字,然后构建矩阵,然后重命名所有内容。
谢谢大家。
这里有一些解决方案。不需要包。
1) table
table(vectorRows, vectorCols)
给予:
vectorCols
vectorRows 1 2 3
1 0 1 0
2 1 0 2
3 1 0 0
请注意,如果有任何行或列没有条目,则不会出现。
2) 聚合
ag <- aggregate( Freq ~ ., data.frame(Freq = 1, vectorRows, vectorCols), sum)
countMat[as.matrix(ag[-3])] <- ag[[3]]
给予:
> countMat
[,1] [,2] [,3]
[1,] 0 1 0
[2,] 1 0 2
[3,] 1 0 0
3) xtabs
xtabs(~ vectorRows + vectorCols)
给予:
vectorCols
vectorRows 1 2 3
1 0 1 0
2 1 0 2
3 1 0 0