【发布时间】:2018-01-24 23:48:19
【问题描述】:
我的问题不是专门针对 R 包(我不这么认为。如果是这样我道歉),而是在创建函数时如何构造灵活的函数输入。我将使用一个示例,使用 R 包 rootSolve 中名为 multiroot() 的函数(它执行 Newton Raphson 方法来查找根)。
要使 multiroot() 工作,您必须首先创建一个函数,该函数是某个方程组的向量。然后将此函数作为输入传递给函数 multiroot()。
例如:
require(rootSolve)
model <- function(x) c(F1 = x[1]^2+ x[2]^2 -1, F2 = x[1]^2- x[2]^2 +0.5)
ss <- multiroot(f = model, start = c(1, 1))
一切都很好。但是,假设 F1 是动态的,这意味着我的方程式可能会根据我在其他地方收集的数据点的数量而改变。我有代码可以吐出一个方程式。目前,等式是一个字符串。例如eq1 <- "x[1]^2 + x[2]^2 - 1"
所以现在如果我尝试替换其他地方的方程式,它会变成(注意 F1):
model <- function(x) c(F1 = eq1, F2 = x[1]^2- x[2]^2 +0.5)
ss <- multiroot(f = model, start = c(1, 1))
我收到错误:stode(y, times, func, parms = parms, ...) 中的错误: REAL() 只能应用于“数字”,不能应用于“字符”
我可以从错误中看到它想要数字,但是eq1 <- as.numeric(eq1) 返回“NA”,所以这显然行不通。 R 不会将所有字符都理解为数字
如果我尝试eq1 <- as.symbol(eq1),我会得到与“列表”而不是“字符”相同的错误。
如果我尝试eq1 <- expression(eq1),我会得到与“表达式”而不是“列表”相同的错误。
也许我的最终问题变成了“我如何使这个等式变成数字?”,但我不这么认为。我不明白为什么 R 认为原始输入是数字。
我绝望地尝试过的其他事情包括只制作一个简单的函数来在包之外进行测试。
#Test with generic function
model2 <- function(x) 2*x[1]- x[2]^2+5
model2(c(2,3))
效果很好!
现在进行替换:
eq2 <- noquote("2*x[1]- x[2]^2+5")
eq2 <- substitute(2*x[1]- x[2]^2+5)
eq2 <- quote(2*x[1]- x[2]^2+5)
eq2 <- expression(2*x[1]- x[2]^2+5)
eq2 <- as.symbol(2*x[1]- x[2]^2+5)
#Test with generic function
model2 <- function(x) eq2
model2(c(2,3))
虽然没有错误,但输出未提供预期结果。相反,它大部分时间都返回2*x[1]- x[2]^2+5。我知道每个都有不同的结构、类等。
所以,我的问题是如何通过输入一个可以在代码中其他地方更改的变量来使函数输入动态化?我希望它与我在示例中使用的包一起使用,但希望我的问题不依赖于包。我的具体问题可能是如何将作为字符串的变量转换为数字,但这对我来说不太有意义。
感谢您提供的任何帮助。
【问题讨论】:
-
你也可以从组件中构造一个函数,但我不确定它是否是你想要的:
f <- function() {}; body(f) <- expression(x[1]^2 + x[2]^2 - 1); formals(f) <- alist(x=)或一次性完成:as.function(alist(x=, x[1]^2 + x[2]^2 - 1)) -
我认为这可能是重复的:stackoverflow.com/questions/29421816/…
-
@42 是的,看起来很相似。接得好!我看到你是那个回答的人。在发帖之前我确实搜索了很多。
标签: r