gsub中的反向评估时间

时间:2013-10-06 21:37:24

标签: r evaluation gsub

我正在尝试生成组合n个高斯的函数,并使用从nls运行中检索的值。我使用gsub使用反向引用将原始系数替换为nls。但是,似乎数据名称上的[\\1之前进行了评估。

这是一个MWE:

nls <- data.frame(Estimate = seq(1,3))
row.names(nls) <- c("a","b","c")
gsub("(a|b|c)",paste0(" ",nls["\\1","Estimate"]," "),"a + b*x + c*x^2")

如您所见,替换是NA,而对nls数据帧的调用似乎是有效的:

gsub("(a|b|c)",paste0(" ","\\1","Estimate"," "),"a + b*x + c*x^2")

延迟评估[

的任何想法

谢谢!

编辑:为了清楚起见,这里的全功能现在工作得很好(它需要峰值数,一个峰的公式,公式中的参数,变量,常量布尔值和nls结果作为参数,并返回在ggplot的{​​{1}}中使用的公式:

stat_function()

这是一个用法示例(为了长度不包括nls数据):

Generate_func <- function(peakNb,peakForm,peakParams, peakVar, constBool,nls){
  res <- as.data.frame(summary(nls)$coefficients, optional = T)
  rhs <- strsplit(peakForm, "~")[[1]][[2]]
  regex <- paste0("([*+-/\\^\\(\\)[:space:]]|^)(",paste0(peakParams, collapse = "|"),")([*+-/\\^\\(\\)[:space:]]|$)")
  exp_names <- paste0(sapply(seq(1,peakNb),function(i){
    paste0(sapply(peakParams, function(j){
      paste0(j,i)
    }))
  }))
  if(constBool){exp_names <- c("C", exp_names)}
  func_text <- paste0(sapply(seq(1,peakNb),function(n){gsubfn(regex, x + y + z ~ paste0(x,res[paste0(y,n),"Estimate"],z), rhs )}), collapse = " + ")
  func_text <- paste0(ifelse(constBool,paste0(res["C","Estimate"]," + "),""), func_text)

  func <- function(x){
    eval(parse(text = func_text))
  }
  names(formals(func)) <- c(peakVar)

  print(func_text)

  func
}

感谢您的帮助!

2 个答案:

答案 0 :(得分:5)

1) gsub用常量替换模式,但您要做的是将其替换为将函数应用于匹配字符串的结果。 gsubfn package中的gusbfn就是这样做的。下面,第二个参数中的公式只是gsubfn的函数的简写形式,其参数是左侧,正文是右侧。或者,第二个参数可以用通常的函数符号(function(x) nls[x,])表示,但代价是冗长:

> library(gsubfn)
> gsubfn("a|b|c", x ~ nls[x, ], "a + b*x + c*x^2")
[1] "1 + 2*x + 3*x^2"

请注意"a|b|c"可以使用nlspaste(rownames(nls), collapse = "|")派生,以避免冗余规范。

2)尽管gsubfn显着简化了这一点,但在没有使用gsubfn substitute的情况下执行此操作:

> L <- as.list(setNames(nls[[1]], rownames(nls)))  # L <- list(a = 1L, b = 2L, c = 3L)
> e <- parse(text = "a + b * x + c * x ^ 2")[[1]]  # e is the text as a "call" object
> s <- do.call(substitute, list(e, L))             # perform the substitution
> format(s)                                        # convert to character
[1] "1L + 2L * x + 3L * x^2"

L是由于问题中定义的nls包含整数这一事实。如果您不喜欢,请在运行上述内容之前将它们转换为数字:

nls[[1]] <- as.numeric(nls[[1]])

3)另一种可能性是循环遍历要替换的字符串。

> s <- "a + b*x + c*x^2"
> for(nm in rownames(nls)) s <- gsub(nm, nls[nm, ], s)
> s
[1] "1 + 2*x + 3*x^2"

如果我们知道每个要更换的内容不超过一次,我们可以使用sub代替gsub

更新:更正了第二个解决方案。

更新2:添加了第三个解决方案。

答案 1 :(得分:1)

这是另一种方法

gsub(paste0(row.names(nls), "(.*)", collapse=""),  paste0(t(nls),  paste0("\\", 1:nrow(nls)), collapse=""), "a + b*x + c*x^2"  )
[1] "1 + 2*x + 3*x^2"