矩阵运算:索引逻辑到数值比较的不对称向量
Posted
技术标签:
【中文标题】矩阵运算:索引逻辑到数值比较的不对称向量【英文标题】:Matrix operation: indexing asymmetric vectors of logical to numerical comparisons 【发布时间】:2012-12-21 02:22:10 【问题描述】:我正在使用逻辑矩阵来选择和排序数字矩阵中相应元素的索引(两者具有相同的维度)。例如,
x <- c(FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE)
y <- c(7, 10, 3, 1, 6, 8, 2, 11, 1, 5)
order(y[x],decreasing=TRUE)
[1] 5 1 4 3 2 6
# NOTE: these are the **indices** of the ordered vector y[x] now containing
# only six elements (10,3,6,8,11,1)
太好了。正常工作。然而,当我对一个矩阵进行运算时,却得到了一个意想不到的结果:
x <- matrix(rep(c(F,T,T),10), nrow=10)
[,1] [,2] [,3]
[1,] FALSE TRUE TRUE
[2,] TRUE TRUE FALSE
[3,] TRUE FALSE TRUE
[4,] FALSE TRUE TRUE
[5,] TRUE TRUE FALSE
[6,] TRUE FALSE TRUE
[7,] FALSE TRUE TRUE
[8,] TRUE TRUE FALSE
[9,] TRUE FALSE TRUE
[10,] FALSE TRUE TRUE
y <- matrix( round(rnorm(30,sample(10))), ncol=3)
[,1] [,2] [,3]
[1,] 7 7 6
[2,] 10 12 8
[3,] 3 5 6
[4,] 1 1 0
[5,] 6 5 6
[6,] 8 7 7
[7,] 2 3 4
[8,] 11 8 9
[9,] 1 2 1
[10,] 5 5 5
y<-structure(c(7, 10, 3, 1, 6, 8, 2, 11, 1, 5, 7, 12, 5, 1, 5, 7,
3, 8, 2, 5, 6, 8, 6, 0, 6, 7, 4, 9, 1, 5), .Dim = c(10L, 3L))
order(y[x], decreasing=TRUE)
[1] 8 5 1 4 12 7 17 3 14 15 10 13 20 18 2 11 6 9 19 16
似乎当比较返回长度不等的向量(取决于 x 中的逻辑 TRUE)时,我正在破坏操作的预期行为。然而,
y[x]
[1] 10 3 6 8 11 1 7 12 1 5 3 8 5 6 6 0 7 4 1 5
无需排序即可获得我期望的结果; order(y[x]) 对所有 TRUE 元素执行。这是一个错误吗?我会(天真地)期望它会分别对每一列执行操作并像上面一样连接结果。
在任何情况下,是否有合理的方法将不对称结果划分为矩阵?我考虑用 NA 填充每个向量到 max dim(x),然后 cbind 成一个矩阵(见下文)。看起来像一团糟,因为我会失去矢量化。还有更优雅的想法/提示吗?
谢谢。
#Desired result
[,1] [,2] [,3]
[1,] 5 2 4
[2,] 1 6 1
[3,] 4 1 2
[4,] 3 4 7
[5,] 2 7 5
[6,] 6 5 6
[7,] NA 3 3
【问题讨论】:
【参考方案1】:我不确定您为什么要使用 NA 保留矩阵结构。你不能使用列表列表吗?在这种情况下,您可以将矩阵转换为数据框并使用 mapply。这就是您在 R 中独立地对每一列执行函数的方式。
my.order <- function(x, y) order(y[x],decreasing=TRUE)
mapply(my.order, as.data.frame(x), as.data.frame(y))
$V1
[1] 5 1 4 3 2 6
$V2
[1] 2 6 1 4 7 5 3
$V3
[1] 4 1 2 7 5 6 3
如果确实需要,您可以随时填充每个元素并将列表强制转换为数据框。
【讨论】:
感谢您对使用列表的建议。我将尝试一些真实的数据集——数千万的规模——并报告执行速度。 好的,让我们知道。我不知道有矢量化版本的 order,如果您担心性能,您可能必须用编译语言编写代码和循环。您可能想查看 Rcpp 包,它允许在 R 脚本中编写和编译 C++ 代码。【参考方案2】:y[x]
返回
[1] 8 5 1 4 12 7 17 3 14 15 10 13 20 18 2 11 6 9 19 16
这是一个数值向量。
order(y[x])
因此正在处理数字向量。它没有记忆 y
和 x
是矩阵,也没有能力读懂你的想法,它应该按列应用到曾经是 3 列的矩阵,并且你想用 NA
值填充它。
您可以使用is.na<-
并返回一个列表(类似于我写这篇文章时发布的答案)
newy <- y
is.na(newy) <- !x
apply(newy, 2,function(x) order(na.omit(x), reduction = TRUE))
[[1]]
[1] 5 1 4 3 2 6
[[2]]
[1] 2 6 1 4 7 5 3
[[3]]
[1] 4 1 2 7 5 6 3
【讨论】:
感谢您的上述建议。我将尝试一些真实的数据集——数千万的规模——并报告这两种方法的执行速度。以上是关于矩阵运算:索引逻辑到数值比较的不对称向量的主要内容,如果未能解决你的问题,请参考以下文章