【问题标题】:Pass in function as input and return function传入函数作为输入和返回函数
【发布时间】:2015-12-09 09:15:11
【问题描述】:

我想编写一个 R 函数,它采用 x 中的数学函数并在 x 中返回一个新函数作为输出。例如:

输入应作为数学函数(或关系)传入x

g <- x^2 + 9*x + log(x)

结果输出应该是:

function(x) (exp(g))

即我想在这个说明性示例中返回 x 中原始函数的符号指数表达式,即 exp(x^2 + 9*x + log(x))

所以理想情况下它会返回函数对象:

function(x) (exp(x^2 + 9*x + log(x)))

我尝试如下:

test <- function(g){
h <- function(x){exp(g)}
return(h)
}
m <- test(x^2 + 9*x + log(x))
m(10)

所以 m(10) 应该返回:

exp(10^2 + 9*10 + log(10))

在这种情况下是 exp(192.3026)。

谁能告诉我如何做到这一点?

【问题讨论】:

  • 这类似于符号微分,不是吗? deriv(expr, ...)
  • 否 - 这里不涉及区分。只想从作为输入传入的函数(即 x^2 + 9*x + log( x))。
  • 因为我写了“相似”。我知道你想要符号表达式的另一种转换。
  • 当然 - 在功能转换的意义上它是相似的 - 是的
  • 是的@JoshO'Brien - 你是对的。我的意思是“exp(192.3026)”。现在已编辑谢谢!

标签: r


【解决方案1】:

你可以使用包函数:

library(functional)
fun <- Compose(function(x) x^2 + 9*x + log(x), exp)
fun(1)
#[1] 22026.47

【讨论】:

  • 请考虑编辑您的帖子,以添加更多关于您的代码的作用以及它为何能解决问题的说明。一个大部分只包含代码的答案(即使它正在工作)通常不会帮助 OP 理解他们的问题。
  • @SuperBiasedMan 请停止发布这些无用的 cmets。
  • @SuperBiasedMan 请考虑在审查自动 cmets 时使用更多克制。虽然通常通用 cmets 可以成为问答的建设性补充,但无法识别需要冗长解释的代码和通常不需要的代码之间的区别的 cmets 无助于改进 StackOverflow 上的内容。 ;)
【解决方案2】:

这是一种方法:

test <- function(e) {
    ee <- substitute(e)
    eee <- substitute(exp(X), list(X=ee))
    f <- function(x) {}
    body(f) <- eee
    environment(f) <- parent.frame()
    f
}

## Check that it works
m <- test(x^2 + 9*x + log(x))
m
# function (x) 
# exp(x^2 + 9 * x + log(x))
m(1)
# [1] 22026.47
m(1) == exp(10)
# [1] TRUE

【讨论】:

  • 有关以编程方式构建函数的更多信息,see here
  • 请考虑编辑您的帖子,以添加更多关于您的代码的作用以及它为何能解决问题的说明。一个大部分只包含代码的答案(即使它正在工作)通常不会帮助 OP 理解他们的问题。
  • @SuperBiasedMan -- 请考虑具体指出您不理解并希望获得帮助的代码的内容。或者您是否碰巧知道 OP,并且知道仅包含代码的答案(使用常见且有据可查的函数)对他们没有帮助? (在这种情况下,我的错 - 你能否给我一些关于他们作为 R 用户的经验的指示,也许让他们就自己的问题与我联系?)
【解决方案3】:

编辑 - 有问题的功能

f <- function(...) {
  l <- eval(substitute(alist(x = x, ...)))
  l[[2]] <- substitute(exp(X), list(X = l[[2]]))
  as.function(`names<-`(l, l[sapply(l, is.symbol)]))
}

g <- f(x^2 + 2*x + 5)
# function (x = x) 
#   exp(x^2 + 2 * x + 5)

g(1)
# [1] 2980.958

这是一般情况的另一种方式:

f <- function(...) {
  l <- eval(substitute(alist(...)))
  as.function(`names<-`(l, l[sapply(l, is.symbol)]))
}

g <- f(x, x^2 + 9*x + log(x))

# function (x = x) 
#   x^2 + 9 * x + log(x)

g(10)
# [1] 192.3026

此版本也适用于任意数量的变量,只需定义它们后跟函数:

g <- f(x, y, z, x + 2 * y + z ** 3)

# function (x = x, y = y, z = z) 
#   x + 2 * y + z^3

g(1, 2, 0)
# [1] 5

可能有更好的方法将... 添加到函数中,但您可以这样做

f <- function(..., use_dots = FALSE) {
  l <- eval(substitute(alist(...)))
  if (use_dots)
    l <- c(head(l, -1), list('...' = as.symbol('...')), tail(l, 1))
  as.function(`names<-`(l, l[sapply(l, is.symbol)]))
}

所以现在您不必命名所有变量/参数

g <- f(x, y, plot(x, y, ...), use_dots = TRUE)
g(1:5, 1:5, main = 'main title', pch = 16, col = 3, cex = 3, xpd = NA)

【讨论】:

  • 谢谢。我为我的应用程序尝试了以下方法,但效果不佳: f names<-(l, l [sapply(l, is.symbol)])) } test2
  • 我想返回 exp(function) 然后取它的导数。能否请您提供帮助,因为如果我能让它起作用,这种方法看起来既简洁又有用
  • @user4687531 将 g 更改为 x 即可。变量需要匹配,否则函数不知道用什么,例如test2 &lt;- function(x) f(x, exp(x))
  • 我认为这不会按预期工作。如果我做 y
  • @user4687531 查看编辑。原本打算在第一个版本中通过g &lt;- f(x, exp(x^2 + 9*x + log(x))) 执行此操作,但我离开了exp。因为您想要的功能总是使用exp,所以这不太通用,并且需要像在编辑中那样处理特殊情况,所以现在使用该版本的f,您可以按预期简单地执行g &lt;- f(x^2 + 9*x + log(x))。我的意思是不太通用,因为这个函数只有一个变量 x,并且只会采用 exp(...) 的形式,其中 ... 是你传递给 f 的任何内容
猜你喜欢
  • 1970-01-01
  • 2021-04-19
  • 2018-12-24
  • 2020-08-06
  • 2014-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-05
相关资源
最近更新 更多