我正在尝试生成组合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")
Run Code Online (Sandbox Code Playgroud)
如您所见,替换是NA,而对nls数据帧的调用似乎是有效的:
gsub("(a|b|c)",paste0(" ","\\1","Estimate"," "),"a + b*x + c*x^2")
Run Code Online (Sandbox Code Playgroud)
任何延迟评估的想法[?
谢谢 !
编辑:为了清楚起见,这里是完整功能现在工作得很好(它需要峰值数,一个峰的公式,公式中的参数,变量,常量布尔值和nls结果作为参数,并返回使用的公式in ggplot:s 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
}
Run Code Online (Sandbox Code Playgroud)
这是一个用法示例(为了长度不包括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))"
Run Code Online (Sandbox Code Playgroud)
谢谢您的帮助 !
1) gsub使用常量替换模式,但您要做的是将其替换为将函数应用于匹配字符串的结果. gusbfn在gsubfn包中做到了.下面,第二个参数中的公式只是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"
Run Code Online (Sandbox Code Playgroud)
请注意,"a|b|c"可以从nls使用paste(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"
Run Code Online (Sandbox Code Playgroud)
该Ls为由于这样的事实nls作为问题定义包含整数.如果您不喜欢,请在运行上述内容之前将它们转换为数字:
nls[[1]] <- as.numeric(nls[[1]])
Run Code Online (Sandbox Code Playgroud)
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"
Run Code Online (Sandbox Code Playgroud)
如果我们知道每个被替换的次数不超过一次,我们就可以sub代替gsub这里使用.
更新:更正了第二个解决方案.
更新2:添加第三个解决方案.
| 归档时间: |
|
| 查看次数: |
335 次 |
| 最近记录: |