R: Использовать external () в пользовательской функции - PullRequest
0 голосов
/ 22 октября 2018

Я хочу использовать пользовательскую функцию с функцией outer.Я хочу использовать каждую комбинацию элементов двух векторов в качестве аргументов для моей функции myfun.

v1= c(30, 60, 100)
v2 = c(30, 60, 100)

myfun = function(x, y){
  rt = unlist(Vectorize(retimes::rexgauss)(n = x, tau = y, mu = 500, sigma = 50))
  ks = ks.test(rt, "pnorm", mean(rt), sd(rt))$p.value
  shap = shapiro.test(rt)$p.value
  z = skew(rt) / sqrt(6/length(rt))
  ztest = pnorm(-abs(z))*2
  results = c(ks, shap, ztest)
  names(results) = c("ks", "shapiro", "ztest")
  return(results)
}

outer(v1, v2, myfun)

Если я делаю это так, я получаю эту ошибку:

Ошибка в dim (robj) <- c (dX, dY): dims [product 9] не соответствуют длине объекта [3] </p>

Я хочу избежать зацикливания всех элементовмои два вектора.Как я могу использовать внешнюю функцию здесь?Как правильно векторизовать мой udf?

1 Ответ

0 голосов
/ 22 октября 2018

Чтобы использовать outer, некоторые основные "требования":

  1. функция будет принимать два вектора одновременно (как показано ниже);решает ли он выполнять над ними векторизованную работу или работать над ними индивидуально,

  2. он должен возвращать вектор такой же длины, как xy);и

  3. вы должны ожидать, что выход будет matrix измерений length(x),length(y).

Интерпретация, что это не все верно для васмы идем дальше.«Правильная функция» зависит от того, как вы хотите, чтобы модель работала.Сопутствующей функцией для outer является expand.gridtidyr::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).

Некоторые параметры:

  1. если вы хотите, чтобы ваша функция вызывалась один раз (как в случае outer) с двумя аргументами, и она выяснит, что делать:

    eg <- expand.grid(x=c(30,60,90), y=c(30, 60, 100))
    do.call("myfunc", eg)
    

    Обратите внимание, что еслис учетом character аргументов он будет (по аналогии с data.frame) создавать factor с по умолчанию.Он принимает аргумент stringsAsFactors=FALSE.

  2. , если вы хотите, чтобы ваша функция вызывалась для каждой пары векторов (так в этом примере 9 раз), тогда сделайте один из них

    myfunc(eg$x, eg$y)
    

    если число векторов известно.Если нет, то используйте eg сверху, тогда

    do.call("mapply", c(myfunc, eg))
    

    должно работать.В зависимости от вывода, вы можете запретить ему «упрощать» вывод (т.е. форсировать вывод list) с помощью

    do.call("mapply", c(myfunc, eg, SIMPLIFY=FALSE))
    
...