R - применить функцию с различным значением аргумента для каждой строки / столбца матрицы

Я пытаюсь применить функцию к каждой строке или столбцу матрицы, но мне нужно передать другое значение аргумента для каждой строки.

Я думал, что знаком с lapply, mapply и т. Д. Но, вероятно, этого недостаточно.

В качестве простого примера:

> a<-matrix(1:100,ncol=10);
> a
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
 [1,]    1   11   21   31   41   51   61   71   81    91
 [2,]    2   12   22   32   42   52   62   72   82    92
 [3,]    3   13   23   33   43   53   63   73   83    93
 [4,]    4   14   24   34   44   54   64   74   84    94
 [5,]    5   15   25   35   45   55   65   75   85    95
 [6,]    6   16   26   36   46   56   66   76   86    96
 [7,]    7   17   27   37   47   57   67   77   87    97
 [8,]    8   18   28   38   48   58   68   78   88    98
 [9,]    9   19   29   39   49   59   69   79   89    99
[10,]   10   20   30   40   50   60   70   80   90   100

Скажем, я хочу применить функцию к каждой строке, я бы сделал:

apply(a, 1, myFunction);

Однако моя функция принимает аргумент, поэтому:

apply(a, 1, myFunction, myArgument);

Но если я хочу, чтобы мой аргумент принимал разные значения для каждой строки, я не могу найти правильный способ сделать это. Если я определю myArgument с несколькими значениями, очевидно, что весь вектор будет передаваться при каждом вызове myFunction.

Я думаю, что мне понадобится некий гибрид между применением и многовариантным отображением. Имеет ли это смысл ?

Один из `` грязных '' способов достижения моей цели - разбить матрицу по строкам (или столбцам), использовать mapply в результирующем списке и объединить результат обратно в матрицу:

do.call(rbind, Map(myFunction, split(a,row(a)), as.list(myArgument)));

Я посмотрел на развертку, агрегирование, все варианты применения *, но я не нашел идеального соответствия моим потребностям. Я пропустил это?

Спасибо за помощь.


person RFen    schedule 07.11.2014    source источник


Ответы (3)


Вы можете использовать sweep для этого.

a <- matrix(rnorm(100),10)
rmeans <- rowMeans(a)
a_new <- sweep(a,1,rmeans,`-`)
rowMeans(a_new)
person Rentrop    schedule 07.11.2014
comment
Похоже, я не очень сильно проснулся, когда попробовал. Ваше предложение еще раз взглянуть на него сделало мой день. Спасибо и прошу прощения за «наивный» вопрос. Надеюсь, позже это поможет кому-то другому. - person RFen; 07.11.2014
comment
После дальнейшего тестирования я вспомнил, почему развертка не сработала. Фактически, в отличие от «apply», функция «sweep» вызовет функцию FUN только один раз, передав ей исходную матрицу и матрицу со значениями, построенными из аргументов «STAT» и «MARGIN». Предполагается, что функция FUN будет выполнять пошаговую операцию с матрицами. Я бы хотел вызвать myFunction для каждой строки (или столбца) исходной матрицы. Для ясности, подходящий пример состоит в применении окна сглаживания с разным размером в каждой строке. - person RFen; 07.11.2014

Я не думаю, что есть какие-то отличные ответы, но вы можете несколько упростить свое решение, используя mapply, который обрабатывает часть "rbind" за вас, предполагая, что ваша функция всегда возвращает вектор того же размера (кроме того, Map на самом деле просто mapply) :

a <- matrix(1:80,ncol=8)
myFun <- function(x, y) (x - mean(x)) * y
myArg <- 1:nrow(a)

t(mapply(myFun, split(a, row(a)), myArg))
person BrodieG    schedule 07.11.2014

Я знаю, что тема довольно старая, но у меня была такая же проблема, и я решил ее таким образом:

# Original matrix
a <- matrix(runif(n=100), ncol=5)
# Different value for each row
v <- runif(n=nrow(a))
# Result matrix -> Add a column with the row number
o <- cbind(1:nrow(a), a)
fun <- function(x, v) {
  idx <- 2:length(x)
  i <- x[1]
  r <- x[idx] / v[i]
  return(r)
}
o <- t(apply(o, 1, fun, v=v)

Добавив столбец с номером строки слева от исходной матрицы, можно получить индекс необходимого значения из вектора аргументов из первого столбца матрицы данных.

person FlorianSchunke    schedule 07.11.2017