R语言brms包如何正确从矩阵提取值传入prior()设置先验
问题原因
核心是brms::prior()用了非标准求值逻辑:它不会立刻计算你传入的分布参数,而是直接把你写的原始表达式存下来,等后续拟合模型时才去执行计算。你写normal(priors[i,1], priors[i,2])的时候,函数直接把priors[i,1]、priors[i,2]这两段代码文本存进去了,根本没提前读取里面的数值。
而lm()这类常规R函数用的是标准求值,传进去的索引会立刻被计算成对应数值,所以同样的索引写法在lm里能正常运行,在prior里不行。
你之前试的几种写法没效果的原因也很明确:
as.numeric()、as.list():这些函数调用本身也被当成表达式存了,没有被提前执行paste()传字符串:prior()不认字符串格式的分布定义,必须是合法的R调用对象get()写法本身有语法错误,就算写对了,get()的调用也会被当成表达式存起来,不会提前执行
可行解决方法
两种写法都能稳定得到你要的结果,选顺手的用即可:
方法1:拼接表达式字符串转公式
把数值直接拼到分布定义的字符串里,转成单边公式传给prior(),写法最简单:
library(brms) priors <- cbind(c(10,20,30,40), c(2,4,6,8)) i <- 1 tmp <- prior( as.formula(paste0("~normal(", priors[i,1], ", ", priors[i,2], ")")), nlpar = "x" )
运行后输出完全符合预期:
#b_x ~ normal(10, 2)
方法2:用do.call构造调用传参
do.call()会在调用目标函数前,先把所有参数求值计算完再传入,刚好能绕开prior()的非标准求值捕获,不需要拼接字符串:
i <- 1 tmp <- do.call( prior, args = list( prior = call("normal", priors[i, 1], priors[i, 2]), nlpar = "x" ) )
如果要批量生成多组先验,直接套循环即可,比如给4个非线性参数批量设先验:
# 初始化空先验集合 priors_set <- brmsprior() nlpar_list <- c("a", "b", "c", "d") for (idx in 1:4) { priors_set <- priors_set + prior( as.formula(paste0("~normal(", priors[idx,1], ", ", priors[idx,2], ")")), nlpar = nlpar_list[idx] ) }
内容的提问来源于stack exchange,提问作者marine-ecologist
相关产品推荐
相关产品推荐

