我正在尝试生成组合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
}
感谢您的帮助!
答案 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"
可以使用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"
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"