Чтобы использовать outer
, некоторые основные "требования":
функция будет принимать два вектора одновременно (как показано ниже);решает ли он выполнять над ними векторизованную работу или работать над ними индивидуально,
он должен возвращать вектор такой же длины, как x
(и y
);и
вы должны ожидать, что выход будет matrix
измерений length(x),length(y)
.
Интерпретация, что это не все верно для васмы идем дальше.«Правильная функция» зависит от того, как вы хотите, чтобы модель работала.Сопутствующей функцией для outer
является expand.grid
(и tidyr::crossing
, версия tidyverse) в том смысле, что она создает те же комбинации предоставленных векторов.Например:
outer(c(30,60,90), c(30, 60, 100), function(x,y) {browser();1;})
# Called from: FUN(X, Y, ...)
# Browse[2]>
x
# [1] 30 60 90 30 60 90 30 60 90
# Browse[2]>
y
# [1] 30 30 30 60 60 60 100 100 100
и
eg <- expand.grid(x=c(30,60,90), y=c(30, 60, 100))
eg
# x y
# 1 30 30
# 2 60 30
# 3 90 30
# 4 30 60
# 5 60 60
# 6 90 60
# 7 30 100
# 8 60 100
# 9 90 100
(к которым затем можно получить доступ как eg$x
и eg$y
).
Некоторые параметры:
если вы хотите, чтобы ваша функция вызывалась один раз (как в случае outer
) с двумя аргументами, и она выяснит, что делать:
eg <- expand.grid(x=c(30,60,90), y=c(30, 60, 100))
do.call("myfunc", eg)
Обратите внимание, что еслис учетом character
аргументов он будет (по аналогии с data.frame
) создавать factor
с по умолчанию.Он принимает аргумент stringsAsFactors=FALSE
.
, если вы хотите, чтобы ваша функция вызывалась для каждой пары векторов (так в этом примере 9 раз), тогда сделайте один из них
myfunc(eg$x, eg$y)
если число векторов известно.Если нет, то используйте eg
сверху, тогда
do.call("mapply", c(myfunc, eg))
должно работать.В зависимости от вывода, вы можете запретить ему «упрощать» вывод (т.е. форсировать вывод list
) с помощью
do.call("mapply", c(myfunc, eg, SIMPLIFY=FALSE))