(R) 如何通过组合较短的变量表达式来编写更大的表达式?
(R) How can a bigger expression be written by combining shorter variable expressions?
简要介绍,我有多个数据文件可以通过基于数学方程的模型进行拟合,这些数学方程是其他较短数学方程的组合(通过求和、乘法等...)。
例如,我有三个短方程:
expression1 <- exp(x)
expression2 <- exp(x^2)
expression3 <- exp(1/x)
因为每个数据文件都有自己更大的表达式,可以产生更好的拟合度,所以我希望能够生成这些更大的表达式作为更短表达式的组合。
我想要的是能够写出这样的东西:
expression1(1) + expression1(2) * expression2(3) + expression2(1)
并得到:
x1 + x2 * x3^2 + 1/x1
稍后我将使用这个更大的方程来找到更适合一个数据文件的值 x1、x2、x3。
exp
是指数函数,因此您的代码并不像您认为的那样工作。要使这样的东西起作用,可能需要使用 print
和 Ops
方法创建一个新的 S3 class:
make_exp <- function(expr) {
expr <- match.call()$expr
function(x) structure(list(val = do.call(substitute, list(expr))),
class = "ex")
}
print.ex <- function(x, ...) print(x$val)
Ops.ex <- function(e1, e2) structure(list(val = call(.Generic, e1$val, e2$val)),
class = "ex")
这允许
expression1 <- make_exp(x)
expression2 <- make_exp(x^2)
expression3 <- make_exp(1/x)
expression1(x1) + expression2(x2) * expression3(x3)
#> x1 + x2^2 * (1/x3)
1) 大概你指的是表达式而不是 exp。进行更改,我们定义 e1、e2、e3 和 e。 esub 是一个函数,它用表达式中的另一个变量名替换变量名。同名包中的 gsubfn 与 gsub 类似,除了第二个参数可以是一个函数(可能像我们在这里那样使用公式表示法表示),它将模式中的捕获组作为参数并用功能。我们 deparse e,使用 gsubfn 并将其解析回来。
library(gsubfn)
e1 <- expression(x)
e2 <- expression(x^2)
e3 <- expression(1/x)
e <- expression(e1(1) + e1(2) * e2(3) + e2(1))
esub <- function(expr, env) do.call("substitute", list(expr, env))
g <- gsubfn("(\w+)[(](\w+)[)]",
~ deparse(esub(get(x)[[1]], list(x = as.name(paste0("x", y))))),
deparse(e))
parse(text = g)[[1]]
## expression(x1 + x2 * x3^2 + x1^2)
2) 如果希望使用字符串而不是表达式,它甚至更短:
library(gsubfn)
s1 <- "x"
s2 <- "x^2"
s3 <- "1/x"
s <- "s1(1) + s1(2) * s2(3) + s2(1)"
gsubfn("(\w+)[(](\w+)[)]", x + y ~ gsub("\bx\b", paste0("x", y), get(x)), s)
## [1] "x1 + x2 * x3^2 + x1^2"
简要介绍,我有多个数据文件可以通过基于数学方程的模型进行拟合,这些数学方程是其他较短数学方程的组合(通过求和、乘法等...)。
例如,我有三个短方程:
expression1 <- exp(x)
expression2 <- exp(x^2)
expression3 <- exp(1/x)
因为每个数据文件都有自己更大的表达式,可以产生更好的拟合度,所以我希望能够生成这些更大的表达式作为更短表达式的组合。
我想要的是能够写出这样的东西:
expression1(1) + expression1(2) * expression2(3) + expression2(1)
并得到:
x1 + x2 * x3^2 + 1/x1
稍后我将使用这个更大的方程来找到更适合一个数据文件的值 x1、x2、x3。
exp
是指数函数,因此您的代码并不像您认为的那样工作。要使这样的东西起作用,可能需要使用 print
和 Ops
方法创建一个新的 S3 class:
make_exp <- function(expr) {
expr <- match.call()$expr
function(x) structure(list(val = do.call(substitute, list(expr))),
class = "ex")
}
print.ex <- function(x, ...) print(x$val)
Ops.ex <- function(e1, e2) structure(list(val = call(.Generic, e1$val, e2$val)),
class = "ex")
这允许
expression1 <- make_exp(x)
expression2 <- make_exp(x^2)
expression3 <- make_exp(1/x)
expression1(x1) + expression2(x2) * expression3(x3)
#> x1 + x2^2 * (1/x3)
1) 大概你指的是表达式而不是 exp。进行更改,我们定义 e1、e2、e3 和 e。 esub 是一个函数,它用表达式中的另一个变量名替换变量名。同名包中的 gsubfn 与 gsub 类似,除了第二个参数可以是一个函数(可能像我们在这里那样使用公式表示法表示),它将模式中的捕获组作为参数并用功能。我们 deparse e,使用 gsubfn 并将其解析回来。
library(gsubfn)
e1 <- expression(x)
e2 <- expression(x^2)
e3 <- expression(1/x)
e <- expression(e1(1) + e1(2) * e2(3) + e2(1))
esub <- function(expr, env) do.call("substitute", list(expr, env))
g <- gsubfn("(\w+)[(](\w+)[)]",
~ deparse(esub(get(x)[[1]], list(x = as.name(paste0("x", y))))),
deparse(e))
parse(text = g)[[1]]
## expression(x1 + x2 * x3^2 + x1^2)
2) 如果希望使用字符串而不是表达式,它甚至更短:
library(gsubfn)
s1 <- "x"
s2 <- "x^2"
s3 <- "1/x"
s <- "s1(1) + s1(2) * s2(3) + s2(1)"
gsubfn("(\w+)[(](\w+)[)]", x + y ~ gsub("\bx\b", paste0("x", y), get(x)), s)
## [1] "x1 + x2 * x3^2 + x1^2"