Использование do.call() в теле нерабочей функции

#r #function

#r #функция

Вопрос:

В настоящее время у меня есть следующий рабочий фрагмент кода:

 my_func <- function(form, char_vars, values) {
  ext_char_vars <- c(char_vars, "x")
  arglist <- lapply(ext_char_vars, function(x) NULL)
  f <- as.function(append(setNames(arglist, ext_char_vars), quote({})))
  deriv(form, char_vars, f)
}

f1 <- my_func(y ~ a0   a1*x   a2*x^2, c("a0", "a1", "a2"))

grad <- attr(f1(a0 = 1, a1 = 2, a2 = 1.5, x = 3), "gradient")
  

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

     my_func <- function(form, char_vars, values) {
      ext_char_vars <- c(char_vars, "x")
      arglist <- lapply(ext_char_vars, function(x) NULL)
      f <- as.function(append(setNames(arglist, ext_char_vars), quote({})))
      f1 <- deriv(form, char_vars, f)
      f2 <- function(x_val){
        attr( do.call(f1, as.list(values, x_val)), "gradient")
      }
      return(f2)
    }


f1 <- my_func(y ~ a0   a1*x   a2*x^2, c("a0", "a1", "a2"), c(1, 2, 1.5))


f1(3)
  

Кто-нибудь может помочь мне выяснить, что я сделал не так, или мне следует использовать другой подход?

Большое спасибо,

Комментарии:

1. напишите f2 так: f2 <- function(x_val){ attr( do.call(f1, as.list(c(values, x_val))), "gradient") } внутри my_func

Ответ №1:

Это работает.

 my_func <- function(form, char_vars, values) {
  ext_char_vars <- c(char_vars, "x")
  arglist <- lapply(ext_char_vars, function(x) NULL)
  f <- as.function(append(setNames(arglist, ext_char_vars), quote({})))
  f1 <- deriv(form, char_vars, f)
  f2 <- function(x_val) {
    attr(do.call(f1, as.list(c(values, x_val)), "gradient")
  }
  return(f2)
}
f1 <- my_func(y ~ a0   a1*x   a2*x^2, c("a0", "a1", "a2"), values=c(1, 2, 1.5))

f1(3)
# a0 a1 a2
# [1,]  1  3  9
  

Объяснение:

Вам нужны аргументы в виде списка, поэтому вы просто хотите c values выполнить их повторную обработку x_val и преобразовать as.list . Without c as.list игнорирует второй аргумент.

 as.list(c(values, x_val))
# [[1]]
# [1] 1
# 
# [[2]]
# [1] 2
# 
# [[3]]
# [1] 1.5
# 
# [[4]]
# [1] 3
  

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

 mean(10, 15)
# [1] 10

mean(c(10, 15))
# [1] 12.5
  

Комментарии:

1. Отлично, спасибо! Я этого не заметил. Мне не нужен оператор точка-точка-точка в функции f2, не так ли?

2. @Kezrael Я добавил пример, mean который должен прояснить ситуацию. Нет, извините, вам это не понадобится ... , просто отредактировал.

3. хорошо, теперь я это ясно вижу. Было сложно изучить и придумать некоторые вещи, чтобы написать функцию так, как я хочу, что, похоже, я упустил из виду основы. Спасибо