функция возвращает как другой параметр функции с помощью eval() в R

Мне трудно научиться использовать eval() для оценки функции,

предположим, у меня есть функция:

sq <- function(y){ y**2 }

вы можете оценить эту функцию следующим образом:

call <- match.call(expand.dots = FALSE)
call[[1]] <- as.name('sq')
call$y <- 0.2
call <- call[c(1,3)]
eval(call)

и это даст и 0,2 ^ 2 = 0,04

Но если я хочу вычислить что-то вроде sq(y), где y = sin(x), я могу написать:

call <- match.call(expand.dots = FALSE)
call[[1]] <- as.name('sq')
call$y <- as.name('sin')
call$x <- 0.2
call <- call[c(1,3:4)]
eval(call)

это даст мне эту ошибку:

Error in sq(y = sin, x = 0.2) : unused argument (x = 0.2)

Кажется, что R не может распознать x как аргумент sin, а вместо этого является аргументом sq. как мы можем сказать R, что x является аргументом греха?

Кроме того, кажется, что R - единственный язык, который я изучил, который использует eval() для оценки функции (я знаю C++ и Python, но раньше не видел этот синтаксис), в чем отличие (или преимущество) для оценки функции в таким образом вместо вызова sq(y=sin(x=0.2))?

Есть ли хорошая книга или учебник, рассказывающий о его использовании и о том, когда использовать между двумя способами? Спасибо!

PS: приведенный выше пример на самом деле представляет собой упрощенную версию кода в пакете mlogit, который я изучаю, в котором вероятность журнала возвращается путем вызова «lnl.slogit», передается в «mlogit.optim» и оптимизируется (строка 407 из https://github.com/cran/mlogit/blob/master/R/mlogit.R). Я использовал тот же метод, что и код в пакете, для вызова двух функций, но получил указанную выше ошибку.


person John    schedule 16.05.2018    source источник


Ответы (1)


Код пытается пройти:

  • аргумент с x по sq, но sq не имеет аргумента x
  • функция sin в аргументе y, но требуется число, а не функция.

Попробуй это:

x <- 0.2
cl <- call("sq", y = quote(sin(x)))

cl
## sq(y = sin(x))

eval(cl)
## [1] 0.0394695

или, может быть, вы хотите:

x <- 0.2
cl <- call("sq", y = sin(x))

cl
## sq(y = 0.198669330795061)

eval(cl)
## [1] 0.0394695

or

match.fun("sq")(sin(x))
## [1] 0.0394695

или просто:

sq(sin(x))
## [1] 0.0394695

Обратите внимание, что обычно вам не нужно использовать eval. Достаточно просто перечислить функцию с ее аргументами, чтобы оценить ее как последнюю строку кода.

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

person G. Grothendieck    schedule 16.05.2018
comment
спасибо за ваш ответ, но в пакете mlogit он вызывает две функции «lnl.slogit» и «mlogit.optim» так же, как и в моем примере, есть ли разница между ними? почему это работает? «R внутренне использует нестандартный код из-за соображений, связанных с окружением» ‹ — есть ли какая-нибудь книга, объясняющая, почему это нужно делать? - person John; 17.05.2018
comment
Я думаю, что вы упустили ключевую часть в своем примере, а именно то, что это не eval(call), а eval(call, parent.frame()), так что любые оцениваемые выражения берут свои свободные переменные из родительского фрейма, а не из среды выполнения mlogit. - person G. Grothendieck; 17.05.2018