多项回归的多重插补和 mlogit

Multiple imputation and mlogit for a multinomial regression

我正在尝试 运行 使用估算数据进行多项式回归。我可以用 nnet 包做到这一点,但我想使用 mlogit。使用 mlogit 包我不断收到以下错误“1:nrow(data) 中的错误:长度为 0 的参数”。

所以制作数据

library(mlogit)
library(nnet)
library(tidyverse)
library(mice)

df <- data.frame(vax = sample(1:6, 500, replace = T),
                 age = runif(500, 12, 18),
                 var1 = sample(1:2, 500, replace = T),
                 var2 = sample(1:5, 500, replace = T))

# Create missing data using the mice package:
df2 <- ampute(df, prop = 0.15)
df3 <- df2$amp

df3$vax <- as.factor(df3$vax)
df3$var1 <- as.factor(df3$var1)
df3$var2 <- as.factor(df3$var2)

# Inpute missing data:
df4 <- mice(df3, m = 5, print = T, seed = 123)

它使用 nnet 的多项式工作:

multinomtest <- with(df4, multinom(vax ~ age + var1 + var2, data = df, model = T))
summary(pool(multinomtest))

但是当我尝试将数据重塑为 mlogit 格式时出现错误

test <- with(df4, dfidx(data = df4, choice = "vax", shape = "wide"))

有谁知道我如何将插补数据转换为 mlogit 格式,或者 mlogit 是否与鼠标或任何其他插补包兼容?

提供此作为避免错误的方法 dfidx():

df5 <- df4$imp %>% 
  # work with a list, where each top-element is a different imputation run (imp_n)
  map(~as.list(.x)) %>%
  transpose %>%
  # for each run, impute and return the full (imputed) data set
  map(function(imp_n.x) {
    df_out <- df4$data
    df_out$vax[is.na(df_out$vax)] <- imp_n.x$vax
    df_out$age[is.na(df_out$age)] <- imp_n.x$age
    df_out$var1[is.na(df_out$var1)] <- imp_n.x$var1
    df_out$var2[is.na(df_out$var2)] <- imp_n.x$var2
    return(df_out)
  }) %>%
  # No errors with dfidx() now
  map(function(imp_n.x) {
    dfidx(data = imp_n.x, choice = "vax", shape = "wide")
  })

不过,我对mlogit()不太熟悉,所以帮不上忙了。

21 年 8 月 2 日更新

正如@slamballais 在他们的回答中提到的,问题在于您在拟合模型时引用的数据集。我假设 mldata(来自评论部分的代码)是 data.frame?这可能是您看到相同系数的原因 - 您不是指估算的数据集(我在函数中将其标识为 imp_n.x)。函数 purrr::map()lapply() 非常相似,您可以在其中将函数应用于列表的元素。因此,为了让代码正常工作,您需要将 mldata 更改为 imp_n.x:

# To fit mlogit() for each imputed data set
df5 %>%
  map(function(imp_n.x) {
    # form as specified in the comments
    mlogit(vax ~ 1 | age + var1 + var2, 
           data = imp_n.x, 
           reflevel = "1", 
           nests = list(type1 = c('1', '2'), 
                        type2 = c('3','4'), 
                        type3 = c('5','6')))
  }) 

回答

您使用的with.mids不正确,因此这两行代码都是错误的; multinom 行只是没有给出错误。如果您想将多个函数应用于估算数据集,最好使用 lapply:

analyses <- lapply(seq_len(df4$m), function(i) {
  data.i <- complete(df4, i)
  data.idx <- dfidx(data = data.i, choice = "vax", shape = "wide")
  mlogit(vax ~ 1 | age + var1 + var2, 
         data = data.idx, 
         reflevel = "1", 
         nests = list(type1 = c("1", "2"), type2 = c("3","4"), type3 = c("5","6")))
})
test <- list(call = "", call1 = df4$call, nmis = df4$nmis, analyses = analyses)
oldClass(test) <- c("mira", "matrix")
summary(pool(test))

with.mids 的工作原理

当您将 with 应用于 mids 对象(即 mice::mice 的输出)时,您实际上是在调用 with.mids.

如果您使用 getAnywhere(with.mids)(或只输入 mice:::with.mids),您会发现它会做一些事情:

  1. 它遍历所有估算的数据集。
  2. 它使用complete得到一个数据集。
  3. 它以数据集作为环境运行表达式。

第三步是问题。对于使用公式(如 lmglmmultinom)的函数,您可以在给定环境中使用该公式。如果变量不在当前环境中(而是在例如数据框中),您可以通过设置 data 变量来指定新环境。


问题

这是你的两个问题的来源:

  • 在您的 multinom 调用中,您将 data 变量设置为 df。因此,在原始 df 上,您实际上是 运行 您的 multinom 而不是 估算的数据集!

  • 在您的 dfidx 调用中,您再次直接填写 data。这也是错误的。但是,将其留空也会出错。这是因为 with.mids 不填写 data 参数,而只填写环境。这对你来说还不够。


修复multinom

multinom 行的解决方案很简单:只要不指定 data:

multinomtest <- with(df4, multinom(vax ~ age + var1 + var2, model = T))
summary(pool(multinomtest))

如您所见,这将产生截然不同的结果!但重要的是要意识到这就是您想要获得的。


修复 dfidx(和 mlogit)

我们无法使用 with.mids 执行此操作,因为它使用估算的数据集作为环境,但您想使用修改后的数据集(在 dfidx 之后)作为您的环境。所以,我们必须编写自己的代码。您可以使用任何循环函数来执行此操作,例如lapply:

analyses <- lapply(seq_len(df4$m), function(i) {
  data.i <- complete(df4, i)
  data.idx <- dfidx(data = data.i, choice = "vax", shape = "wide")
  mlogit(vax ~ 1 | age + var1 + var2, data = data.idx, reflevel = "1", nests = list(type1 = c("1", "2"), type2 = c("3","4"), type3 = c("5","6")))
})

从那里开始,我们所要做的就是制作一个看起来像 mira 对象的东西,这样我们仍然可以使用 pool:

test <- list(call = "", call1 = df4$call, nmis = df4$nmis, analyses = analyses)
oldClass(test) <- c("mira", "matrix")
summary(pool(test))