首页 > 解决方案 > 矩阵的哪些行等于某个向量

问题描述

我有一段代码搜索矩阵boxes的哪些行等于给定的向量x。此代码使用该apply功能,我想知道它是否可以进一步优化?

x = floor(runif(4)*10)/10
boxes = as.matrix(do.call(expand.grid, lapply(1:4, function(x) {
  seq(0, 1 - 1/10, length = 10)
})))

# can the following line be more optimised ? :
result <- which(sapply(1:nrow(boxes),function(i){all(boxes[i,] == x)}))

我自己并没有设法摆脱这个apply功能,但也许你会有比我更好的主意:)

标签: rapply

解决方案


一种选择是which(colSums(t(boxes) == x) == ncol(boxes))

向量是按列回收的,因此我们需要在与 withboxes进行比较之前进行转置。然后我们可以选择列(转置行)的总和为,即所有值。x==whichncol(boxes)TRUE

这是此(可能不具有代表性)示例的基准

Irnv <- function() which(sapply(1:nrow(boxes),function(i){all(boxes[i,] == x)}))
ICT <- function() which(colSums(t(boxes) == x) == ncol(boxes))
RS <- function() which(rowSums(mapply(function(i, j) boxes[, i] == j, seq_len(ncol(boxes)), x)) == length(x))
RS2 <- function(){ 
  boxes <- data.frame(boxes)
  which(rowSums(mapply(`==`, boxes, x)) == length(x))
}
akrun <- function() which(rowSums((boxes == x[col(boxes)])) == ncol(boxes))


microbenchmark(Irnv(), ICT(), RS(), RS2(), akrun())
# Unit: microseconds
#     expr       min         lq       mean     median         uq       max neval
#   Irnv() 19218.470 20122.2645 24182.2337 21882.8815 24949.1385 66387.719   100
#    ICT()   300.308   323.2830   466.0395   342.3595   430.1545  7878.978   100
#     RS()   566.564   586.2565   742.4252   617.2315   688.2060  8420.927   100
#    RS2()   698.257   772.3090  1017.0427   842.2570   988.9240  9015.799   100
#  akrun()   442.667   453.9490   579.9102   473.6415   534.5645  6870.156   100

推荐阅读