Подтвердить что ты не робот

Почему внешняя работа не так, как мне кажется (в R)?

Подскажите @hadley статью об функционалах, на которые ссылается сегодня в ответе, я решил пересмотреть постоянную загадку о том, как работает функция outer (или не работает). Почему это не удается:

outer(0:5, 0:6, sum) # while outer(0:5, 0:6, "+") succeeds

Это показывает, как я думаю, outer должен обрабатывать такую ​​функцию, как sum:

 Outer <- function(x,y,fun) {
   mat <- matrix(NA, length(x), length(y))
   for (i in seq_along(x)) {
            for (j in seq_along(y)) {mat[i,j] <- fun(x[i],y[j])} }
   mat}

>  Outer(0:5, 0:6, `+`)
     [,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,]    0    1    2    3    4    5    6
[2,]    1    2    3    4    5    6    7
[3,]    2    3    4    5    6    7    8
[4,]    3    4    5    6    7    8    9
[5,]    4    5    6    7    8    9   10
[6,]    5    6    7    8    9   10   11

Хорошо, у меня нет моих индексов, точно выровненных для этого примера, но это было бы не так сложно исправить. Вопрос в том, почему функция типа sum, которая должна иметь возможность принимать два аргумента и возвращать (атомное) значение, подходящее для элемента матрицы, не может сделать это при передаче функции base::outer?

Итак, @agstudy дал вдохновение для более компактной версии outer, и его еще более компактно:

 Outer <- function(x,y,fun) {
       mat <- matrix(mapply(fun, rep(x, length(y)), 
                                 rep(y, each=length(x))),
                     length(x), length(y))

Однако вопрос остается. Термин "векторизованный" здесь несколько неоднозначен, и я думаю, что "диадический" более правильный, поскольку sin и cos "векторизованы" в обычном смысле этого термина. Существует ли фундаментальный логический барьер, ожидающий, что outer расширит свои аргументы таким образом, что могут использоваться недиадические функции.

И вот еще один outer -error, который, вероятно, также связан с моим недостатком понимания этой проблемы:

> Vectorize(sum)
function (..., na.rm = FALSE)  .Primitive("sum")
>  outer(0:5, 0:6, function(x,y) Vectorize(sum)(x,y) )
Error in outer(0:5, 0:6, function(x, y) Vectorize(sum)(x, y)) : 
  dims [product 42] do not match the length of object [1]
4b9b3361

Ответ 1

outer(0:5, 0:6, sum) не работают, потому что sum не "векторизован" (в смысле возврата вектора той же длины, что и два его аргумента). Этот пример должен объяснить разницу:

 sum(1:2,2:3)
  8
 1:2 + 2:3
 [1] 3 5

Вы можете векторизовать sum с помощью mapply, например:

identical(outer(0:5, 0:6, function(x,y)mapply(sum,x,y)),
          outer(0:5, 0:6,'+'))
TRUE

PS: Обычно перед использованием outer я использую browser для создания моей функции в режиме отладки:

outer(0:2, 1:3, function(x,y)browser())
Called from: FUN(X, Y, ...)
Browse[1]> x
[1] 0 1 2 0 1 2 0 1 2
Browse[1]> y
[1] 1 1 1 2 2 2 3 3 3
Browse[1]> sum(x,y)
[1] 27          ## this give an error 
Browse[1]> x+y  
[1] 1 2 3 2 3 4 3 4 5 ## this is vectorized