R中glmer拟合带offset的泊松混合模型报PIRLS NaN错误求助
glmer添加offset触发PIRLS NaN报错排查与模型修正
报错核心诱因
- 数据存在非法计算值:只要添加
offset(log(TRIAL_TIME))就报错,首先排查TRIAL_TIME列的取值:log()函数仅对大于0的有效数值有定义,只要数据中存在试次时长TRIAL_TIME<=0、取值缺失的情况,计算offset时会直接生成-Inf或NaN,传入PIRLS迭代循环后就会触发你看到的报错。从你附的数据样例看,还存在结果变量缺失的问题:多行文末的注视次数字段为空,这类无效行如果不提前剔除,也会导致计算异常。 - 变量名不匹配:你附的样例数据中结果变量列名为
COUNT,但模型公式中调用的结果变量是FIXATION_COUNT,如果数据集没有提前做列名重命名,会直接导致变量读取错误。 - 随机效应结构冗余:你写的第二个模型同时设定了
(1|WORD)和(CONDITION|WORD),后者本身已经包含单词层面的随机截距,重复设定截距项会导致随机效应方差协方差矩阵奇异,进一步加剧数值计算故障。 - 变量类型识别错误:如果
CONDITION没有提前转为因子类型,glmer会默认将其识别为连续变量,结合被试间设计下被试与条件完全嵌套的结构,也可能提升矩阵求逆失败的概率。
可复现的修正流程
- 先做数据清洗与合法性校验,剔除所有会导致计算异常的行:
# 若实际数据中结果变量列名为COUNT,先重命名匹配模型公式 colnames(WORD_DATA)[colnames(WORD_DATA) == "COUNT"] <- "FIXATION_COUNT" # 将分类变量转为因子类型 WORD_DATA$CONDITION <- as.factor(WORD_DATA$CONDITION) # 排查非法值 cat("TRIAL_TIME缺失值数量:", sum(is.na(WORD_DATA$TRIAL_TIME)), "\n") cat("TRIAL_TIME<=0的数量:", sum(WORD_DATA$TRIAL_TIME <= 0, na.rm = T), "\n") cat("FIXATION_COUNT缺失值数量:", sum(is.na(WORD_DATA$FIXATION_COUNT)), "\n") # 生成清洗后的分析数据集 WORD_DATA_clean <- subset( WORD_DATA, !is.na(FIXATION_COUNT) & !is.na(TRIAL_TIME) & TRIAL_TIME > 0 )
- 修正随机效应结构,搭配稳定性更高的优化器重新拟合:
library(lme4) # 基准模型:保留被试、单词的随机截距 Count_1_fixed <- glmer( formula = FIXATION_COUNT ~ CONDITION + offset(log(TRIAL_TIME)) + (1|PARTICIPANT) + (1|WORD), family = poisson(link = "log"), data = WORD_DATA_clean, control = glmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 2e4)) ) # 加入单词层面的条件随机斜率(无需重复设定(1|WORD),随机斜率项已包含对应截距) Count_2_fixed <- glmer( formula = FIXATION_COUNT ~ CONDITION + offset(log(TRIAL_TIME)) + (1|PARTICIPANT) + (CONDITION|WORD), family = poisson(link = "log"), data = WORD_DATA_clean, control = glmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 2e4)) )
模型设定合理性说明
你提到因为是被试间设计,每位被试仅接受一种实验条件,因此不设定被试层面的条件随机斜率,这个处理是完全正确的:被试与条件完全嵌套时,被试层面的条件随机斜率与被试随机截距完全共线,根本无法识别。如果清洗数据后模型仍存在收敛警告,可以进一步检查结果变量是否存在过度离散问题,必要时换用负二项分布混合效应模型即可。
内容的提问来源于stack exchange,提问作者T Song
相关产品推荐
相关产品推荐

