Подскажите @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]