升级mlogit与R版本后出现‘More than one idx column’报错的问询
问题:mlogit v1.1-3 报错 "More than one idx column"
背景代码流程
- 构建初始数据框:
data <- structure(list(personID = c(1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L), problem = c(1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L), choice = c("Right", "Right", "Left", "Middle", "Left", "Middle", "Right", "Right","Right"), valueLeft = c(42.0570675657767, 45.9309219826825, 67.9396886866177, 72.9432649788673, 49.4515911099392, 50.4063604914605, 27.930814474658, 59.6351010950862, 62.4926813609122), valueMiddle = c(44.8488506631671, 46.7573345964733, 34.8353743300335, 53.0737324797719, 53.6425649799281, 22.8107239238157, 70.9399442391851, 61.5264080883177, 52.5180668579461), valueRight = c(63.1719866895542, 49.6082608281623, 62.155490653361, 63.5991448059925, 35.8780394435125, 48.0016025122861, 44.7708824302011, 53.0087719413007, 46.0633500203071)), row.names = c(NA, -9L), class = "data.frame")
- 转换为dfidx格式:
data.logit <- dfidx(data, shape = "wide", choice = "choice", drop.index = TRUE, id.var = "personID" )
- 生成自变量并绑定:
indepvar <- c() for (i in 1:length(data.logit$idx$id2)) { ifelse(data.logit$idx$id2[i]=="Left", indepvar[i] <- data.logit$valueLeft[i], ifelse(data.logit$idx$id2[i]=="Middle", indepvar[i] <- data.logit$valueMiddle[i], ifelse(data.logit$idx$id2[i]=="Right", indepvar[i] <- data.logit$valueRight[i], "" )))} indepvar <- data.frame(indepvar) data.logit <- cbind(data.logit, indepvar) remove(indepvar,i)
- 按
problem字段拆分数据框到列表:
list_menus <- list() for (i in 1:3) { list_menus[[paste0("Problem_",i)]] <- dplyr::filter(data.logit, problem==i) remove(i) }
- 尝试用mlogit批量估计模型时触发报错:
list_estimates <- list() for (i in 1:length(list_menus)) { list_estimates[[i]] <- mlogit(formula = choice ~ 1 + indepvar, data = list_menus[[i]], drop.index = TRUE, id.var = "personID") remove(i) }
报错信息:
Error in idx_name.dfidx(x) : More than one idx column
该问题在mlogit v1.1-1 + R v4.4.1中未出现,升级到mlogit v1.1-3 + R v4.5.1后触发。
原因分析
mlogit v1.1-3对dfidx对象的索引列检查更严格:使用dplyr::filter拆分dfidx格式的数据框时,原有的idx属性会被保留,但拆分后的子数据框中,索引列(如personID对应的id列)会出现重复或冲突,导致mlogit识别到多个索引列,触发报错。
解决方法
方法1:拆分前转换为普通数据框
在拆分前将data.logit转换为普通data.frame,避免保留dfidx的索引属性,之后对每个子数据框单独调用dfidx转换:
# 转换为普通数据框 data.logit_df <- as.data.frame(data.logit) # 拆分数据 list_menus <- list() for (i in 1:3) { list_menus[[paste0("Problem_",i)]] <- dplyr::filter(data.logit_df, problem==i) } # 批量估计模型 list_estimates <- list() for (name in names(list_menus)) { # 对每个子数据框重新转换为dfidx格式 temp_df <- dfidx(list_menus[[name]], shape = "wide", choice = "choice", drop.index = TRUE, id.var = "personID") # 估计模型 list_estimates[[name]] <- mlogit(choice ~ 1 + indepvar, data = temp_df) }
方法2:手动重置子数据框的idx属性
如果要保留dfidx格式,拆分后手动重置每个子数据框的idx属性,确保只有一个有效索引列:
list_menus <- list() for (i in 1:3) { temp <- dplyr::filter(data.logit, problem==i) # 重置idx属性,仅保留personID作为id变量 attr(temp, "idx") <- dfidx(temp, shape = "wide", choice = "choice", drop.index = TRUE, id.var = "personID")$idx list_menus[[paste0("Problem_",i)]] <- temp } # 批量估计模型 list_estimates <- list() for (i in seq_along(list_menus)) { list_estimates[[i]] <- mlogit(choice ~ 1 + indepvar, data = list_menus[[i]]) }
可选优化:简化自变量生成逻辑
原生成indepvar的循环可以替换为向量化操作,提升效率:
library(dplyr) data.logit$indepvar <- with(data.logit, case_when( idx$id2 == "Left" ~ valueLeft, idx$id2 == "Middle" ~ valueMiddle, idx$id2 == "Right" ~ valueRight ) )
内容的提问来源于stack exchange,提问作者user_xyz
相关产品推荐
相关产品推荐

