do.call 和 curve 不能在另一个函数环境中绘制函数
Posted
技术标签:
【中文标题】do.call 和 curve 不能在另一个函数环境中绘制函数【英文标题】:do.call and curve can not plot a function inside another function environment 【发布时间】:2013-01-12 09:59:18 【问题描述】:我遇到了一个关于 do.call 和 curve 的奇怪问题:
func1 <- function (m, n)
charac <- paste ("func2 <- function(x)", m, "*x^", n, sep = "")
eval(parse(text = charac))
return(func2)
func3 <- function (m, n)
my.func <- func1 (m, n)
do.call("curve",list(expr = substitute(my.func)))
func1 构造 func2 和 func3 绘制构造的 func2。 但是当我运行 func3 时,会显示以下错误:
> func3 (3, 6)
Error in curve(expr = function (x) :
'expr' must be a function, or a call or an expression containing 'x'
但是,当我运行 func1 并手动绘制输出(不应用 func3)时,func2 将被绘制:
my.func <- func1 (3, 6)
do.call("curve",list(expr = substitute(my.func)))
这里发生的事情让我很困惑,我不知道为什么 do.call 不能在 func3 本地环境中绘制 func2。
谢谢
【问题讨论】:
【参考方案1】:您让这变得过于复杂 - 创建 f2
时您不需要做任何特别的事情:
f1 <- function (m, n)
function(x) m * x ^ n
f3 <- function (m, n)
f2 <- f1(m, n)
curve(f2)
f3(3, 6)
当然,这可以通过删除 f1
来更简洁:
f4 <- function (m, n)
f2 <- function(x) m * x ^ n
curve(f2)
f4(3, 6)
您可以在https://github.com/hadley/devtools/wiki/Functions 找到有关 R 范围规则的更多信息(使这项工作有效)
【讨论】:
++ :(链接比答案更多)我认为问题是如何将参数传递给在另一个函数中使用do.call
接受表达式参数的函数,但也许我过度了阅读它。阅读您的材料,我想知道问题是否可能是传递的是闭包而不是函数?
@DWin 所有函数都是闭包,所以这可能不是问题。但我真的不明白你在回答中要做什么。您可能还会发现 github.com/hadley/devtools/wiki/Computing-on-the-language 很有帮助,但它仍然很粗糙。 github.com/hadley/pryr/blob/master/R/draw-tree.r 也很有用。
@hadley 是的,我把它弄复杂了,但这只是我主要代码的一个简化示例。如您所知,R 无法处理符号计算(但是有一个名为 Ryacas 的包,它是 yacas 的接口)。在我的代码中,这种方法适用于为非线性模型自动构建 Fisher 信息矩阵,而无需用户干预
@EhsanMasoudi R 确实具有广泛的符号计算能力。【参考方案2】:
不是do.call
的问题,而是substitute
的问题默认在全局环境下求值。
所以 你需要告诉它必须在哪个环境中进行替换。这里显然是在 func3 的本地环境中。
这应该可行:
do.call("curve",list(expr = substitute(my.func,
env = parent.frame())))
编辑感谢 Dwin
正如评论中所说,替代 env 默认为当前评估环境。那么为什么下面的代码有效?答案在substitute
的帮助下
函数的正式参数或使用显式创建的 delayAssign(),promise 的表达式槽替换了 象征。如果是普通变量,则将其值代入, 除非 env 是 .GlobalEnv 在这种情况下符号保持不变。
env = parent.frame(n=1)
等价于.GlobalEnv
,这就是为什么符号 (my.func) 保持不变。所以正确的答案是:
do.call("curve",list(expr = substitute(my.func,
env = .GlobalEnv)))
为了测试,我打开了新的 R 会话:
func1 <- function (m, n)
charac <- paste ("func2 <- function(x)", m, "*x^", n, sep = "")
eval(parse(text = charac))
return(func2)
func3 <- function (m, n)
my.func <- func1 (m, n)
do.call("curve",list(expr = substitute(my.func,env = .GlobalEnv)))
比我说的
func3(2,6)
【讨论】:
@EhsanMasoudi 如果它有效并且您对问题感到满意,您可以通过选中左侧的框来接受它。substitute
的帮助页面说它是在当前环境中评估的。
您能否创建一个此代码不会引发错误的上下文?我得到“找不到函数'my.curve”
不使用新代码,但是当do.call
的第一个参数是“my.curve”时会引发错误。
@DWin 哎呀......更正了!我破解了curve
函数,我忘记删除名称。谢谢你的帮助。【参考方案3】:
这行得通:
func3 <- function (m, n)
my.func <- func1 (m, n); print(str(my.func))
do.call(curve, list(expr=bquote( my.func) ) )
【讨论】:
不过,不知道为什么这种方法有输出。curve
应该是接受一个函数,所以我不明白你的不理解。
对不起,我不是在谈论情节,我是在谈论打印到屏幕上的乱码。
对不起。那个 print() 调用只是我确保 my.func
在那个时候确实是一个函数的方式。可以安全地忽略或删除它。【参考方案4】:
你只需要删除行:
my.func
来自 func3。
【讨论】:
这怎么可能有帮助?以上是关于do.call 和 curve 不能在另一个函数环境中绘制函数的主要内容,如果未能解决你的问题,请参考以下文章