R中用purrr::imap批量拟合glmer模型时遇control参数错误
问题描述
编写了mweFitModelsGLMER函数,单独调用(指定family = binomial()等参数)可正常拟合glmer混合效应模型并输出tibble;但编写辅助函数mweMultipleModelsGLMER时,用purrr::imap传入命名公式列表批量调用该函数,始终报错:'control' is not a list; use glmerControl()——即使显式指定control为glmerControl()对象也无效。改用purrr::map忽略列表名称时,函数运行正常。
原因分析
purrr::imap的核心特性是同时传递列表元素的值和元素的名称:它会把每个元素的值作为第一个参数传给目标函数,元素的名称作为第二个参数。如果你的mweFitModelsGLMER函数依赖位置参数传递,没有明确指定参数名称,就会导致列表的名称(字符串类型)被错误地传递给control参数(原本需要glmerControl对象),从而触发类型错误。
举个典型的错误场景:
假设mweFitModelsGLMER的参数顺序是(formula, control, data, family),你在imap中调用时写:
imap(model_formulas, mweFitModelsGLMER, data = my_data, family = binomial())
此时imap会把列表元素的名称作为第二个参数传给control,导致control接收到字符串而非glmerControl对象,直接触发报错。而map只会传递元素值,不会传递名称,因此不会出现参数错位的问题。
解决方法
在imap的回调函数中明确指定所有参数的名称,避免位置传递导致的参数错位。示例代码如下:
mweMultipleModelsGLMER <- function(model_formulas, data, family, control = glmerControl()) { imap(model_formulas, function(formula, model_name) { # 明确指定每个参数的名称,避免model_name被误传给control等参数 mweFitModelsGLMER( formula = formula, data = data, family = family, control = control ) }) }
这样列表名称model_name只会作为回调函数的局部变量,不会干扰mweFitModelsGLMER的参数传递;如果需要用模型名称做后续处理(比如给结果命名),也可以在回调函数中直接使用model_name。
内容的提问来源于stack exchange,提问作者Rover Eye

