含被试内变量的Beta分布模型拟合:公式设置求助
问题
因变量st服从Beta分布(已用descdist命令验证),需构建对应统计模型。实验设计为3×2:
- 自变量
temp:3水平被试内因子(同一被试不同时间测量) - 自变量
cond:2水平被试间因子(两组不同被试)
需检验主效应与交互效应。
已通过fitdist()拟合分布,使用betareg()构建Beta回归时,无法正确指定被试内/被试间变量:
- 尝试公式
MSTb=betareg(scaledst~temp*cond, data=ds.cy),执行Anova(MSTB)虽得到结果,但未考虑重复测量的嵌套结构。 - 尝试加入被试ID随机效应的公式
MSTb=betareg(scaledst~temp*cond+(1|id), data=ds.cy),报错:
`contrasts<-`(`*tmp*`, value = contr.funs[1 + isOF[nn]]) : the contrast can be applied only to factors variable with 2 or more levels In addition: Warning message: In Ops.factor(1, id) : ‘|’ not meaningful for factors
- 尝试公式
betareg(scaledst~temp*cond+(1+temp|id), data=ds.cy),同样报错:
Error in `contrasts<-`(`*tmp*`, value = contr.funs[1 + isOF[nn]]) : contrasts can be applied only to factors with 2 or more levels In addition: Warning messages: 1: In Ops.factor(1, temp) : ‘+’ not meaningful for factors 2: In Ops.factor(1 + temp, id) : ‘|’ not meaningful for factors
解决方案
核心问题:betareg包仅支持固定效应的Beta回归,不支持(1|id)这类随机效应语法,所以直接在betareg里加被试随机效应会报错。要处理重复测量的混合效应Beta模型,需要用支持混合效应的工具包,比如glmmTMB或lme4。
方法1:使用glmmTMB构建混合效应Beta模型
glmmTMB原生支持Beta分布的混合效应模型,语法和lme4一致,能直接处理被试内/被试间变量:
- 安装并加载包:
install.packages("glmmTMB") library(glmmTMB)
- 构建模型:
# 模型包含固定效应(temp*cond)+ 被试id的随机截距 + temp的随机斜率(对应被试内变量的个体差异) MSTb <- glmmTMB(scaledst ~ temp * cond + (1 + temp | id), data = ds.cy, family = beta_family(link = "logit")) # 可根据需求替换为probit、cloglog等链接函数
- 检验效应:
用car包的Anova()做类型III方差分析,检验主效应和交互效应:
library(car) Anova(MSTb, type = "III")
方法2:使用lme4结合Beta链接
lme4本身没有专门的Beta族,但可以通过自定义链接函数实现,步骤相对繁琐,优先推荐glmmTMB。示例代码:
library(lme4) # 定义Beta分布的链接和方差函数 beta_link <- make.link("logit") beta_variance <- function(mu) mu*(1-mu) # 构建混合模型 MSTb <- glmer(scaledst ~ temp * cond + (1 + temp | id), data = ds.cy, family = binomial(link = beta_link), weights = rep(1, nrow(ds.cy))) # 权重需根据实际情况调整
注意:此方法结果解释和glmmTMB的Beta模型略有差异,需谨慎处理。
额外注意事项
- 确保
temp、cond、id都是因子类型,否则可能导致语法解析错误:
ds.cy$temp <- factor(ds.cy$temp) ds.cy$cond <- factor(ds.cy$cond) ds.cy$id <- factor(ds.cy$id)
- Beta回归要求因变量取值严格在(0,1)之间,若
scaledst包含0或1,需做小范围调整:
scaledst <- ifelse(scaledst==0, 1e-6, ifelse(scaledst==1, 1-1e-6, scaledst))
内容的提问来源于stack exchange,提问作者NicNLM
相关产品推荐
相关产品推荐

