Векторизация, какая операция по строкам матрицы - PullRequest
3 голосов
/ 06 февраля 2020

Я хотел бы векторизовать (apply) операцию which на матрице X, как показано следующим for l oop, имеющим в результате вектор ind:

X   = matrix( 1:20, 4, 5 )
V   = sample( 1:20, 4 )
ind = numeric()
for( i in 1:nrow(X) ) ind[i] = max( c(0, which(X[i,] < V[i]) ))

Операция возвращает в ind для каждой строки в X индекс элемента с наивысшим значением, меньшим, чем значение, указанное * X соответствующим элементу V.

Операция max отображает вектор всех подходящих индексов в скаляр. В качестве альтернативы я был бы доволен операцией, возвращающей, например, list всех индексов (к которым я могу lapply max).

Ответы [ 4 ]

3 голосов
/ 06 февраля 2020
apply(
    (X < V) * X
    , 1
    , which.max
)
3 голосов
/ 06 февраля 2020

Если ваша матрица имеет растущие значения, как пример, которым вы поделились (что, конечно, я сомневаюсь), но если это так, вы можете просто сделать,

rowSums(X < V)
#[1] 4 3 4 0

Однако, если это не так, то будет достаточно простого apply, то есть

apply(X < V, 1, function(i)max(which(i)))
#[1]    4    3    4 -Inf

Помните, что все математические операции векторизованы, поэтому < векторизовано

Вы можете заменить -Inf как обычно

2 голосов
/ 06 февраля 2020

Вот простой пример

X   = matrix( 1:20, 4, 5 )
V   = sample( 1:20, 4 )
ind = numeric()
for( i in 1:nrow(X) ) ind[i] = max( c(0, which(X[i,] < V[i]) ))

mymax = function(matrix, sample) {
    whichlist = which(matrix < sample)
    max(0, whichlist)
}
ind2 = unlist(lapply(1:nrow(X), function(r) mymax(X[r,], V[r])))

identical(ind, ind2)
# [1] TRUE
1 голос
/ 06 февраля 2020

Вот еще один ответ, где вы сначала sweep вектор V в каждой строке X, а затем применяете команду apply, чтобы определить максимальный TRUE элемент каждой строки.

set.seed(14)
X   = matrix( 1:20, 4, 5 )
V   = sample( 1:20, 4 )
ind1 = numeric()
for( i in 1:nrow(X) ) ind1[i] =  max(c(0, which(X[i,] < V[i]) ))



ind2 <- apply(
  sweep(X, 1, V, "<"),
  1,
  function(x){
    max(
    which(
      x,
      arr.ind = TRUE)
    )
  }
)


> ind1
[1] 2 5 2 4
> ind2
[1] 2 5 2 4
...