4

我正在尝试生成组合 n 高斯的函数,并使用从nls运行中检索到的值。我用使用反向引用gsub的系数替换原始系数nls。但是,似乎[datafame 在\\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_stat_function()

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
}

这是一个使用示例(出于长度原因,未包括 nls 数据):

> testfunc <- Generate_func(3, "intensity_cnt ~ a * exp((-(energy_eV-b)^2)/(2*c^2))", c("a","b","c"), "energy_eV", constBool = T, testnls)
[1] "1000 +  32327.6598743022 * exp((-(energy_eV-1.44676439236578)^2)/(2*0.0349194350021539^2)) +  10000 * exp((-(energy_eV-1.49449385009962)^2)/(2*0.0102269096492807^2)) +  54941.8293572164 * exp((-(energy_eV-1.5321664735001)^2)/(2*0.01763494864617^2))"

谢谢您的帮助 !

4

2 回答 2

5

1) gsub用常量替换模式,但您要做的是用将函数应用于匹配字符串的结果替换它。 gusbfngsubfn 包中这样做。下面,第二个参数中的公式只是 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"可以从nlsusingpaste(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"

Ls 是由于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:添加了第三个解决方案。

于 2013-10-06T21:55:56.447 回答
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"
于 2013-10-06T22:09:10.757 回答