2
votes

I am trying to use the lm.cluster function in the package miceadds to get robust clustered standard errors for a multiply imputed dataset.

I am able to get the standard version of it to run but I get the following error when I try to add a subset or weights:

Error in eval(substitute(subset), data, env) : 
..1 used in an incorrect context, no ... to look in

Example that works without subset or weights:

require("mice")
require("miceadds")
data(data.ma01)
# imputation of the dataset: use six imputations
dat <- data.ma01[ , - c(1:2) ]
imp <- mice::mice( dat , maxit=3 , m=6 )
datlist <- miceadds::mids2datlist( imp )
# linear regression with cluster robust standard errors
mod <- lapply(datlist, FUN = function(data){miceadds::lm.cluster( data=data ,         
formula=read ~ paredu+ female ,  cluster = data.ma01$idschool )}  )

# extract parameters and covariance matrix
betas <- lapply( mod , FUN = function(rr){ coef(rr) } )
vars <- lapply( mod , FUN = function(rr){ vcov(rr) } )
# conduct statistical inference
summary(pool_mi( qhat = betas, u = vars ))

Example that breaks with subset:

mod <- lapply(datlist, FUN = function(data){miceadds::lm.cluster( data=data ,         
formula=read ~ paredu+ female ,  cluster = data.ma01$idschool, subset=
(data.ma01$urban==1))}  )

Error during wrapup: ..1 used in an incorrect context, no ... to look in

Example that breaks with weights:

mod <- lapply(datlist, FUN = function(data){miceadds::lm.cluster( data=data ,         
formula=read ~ paredu+ female ,  cluster = data.ma01$idschool,
weights=data.ma01$studwgt)}  )

Error during wrapup: ..1 used in an incorrect context, no ... to look in

From searching, I think I am encountering similar issues as others when passing these commands through an lm or glm wrapper (such as: Passing Argument to lm in R within Function or R : Pass argument to glm inside an R function or Passing the weights argument to a regression function inside an R function)

However, I am not sure how to address the issue with the imputed datasets & existing lm.cluster command.

Thanks

2

2 Answers

2
votes

This works fine with the estimatr package which is on CRAN and the estimatr::lm_robust() function. Two notes: (1) you can change the type of standard errors using se_type = and (2) I keep idschool in the data because we like the clusters to be in the same data.frame as we fit the model on.

library(mice)
library(miceadds)
library(estimatr)

# imputation of the dataset: use six imputations
data(data.ma01)
dat <- data.ma01[, -c(1)] # note I keep idschool in data
imp <- mice::mice( dat , maxit = 3, m = 6)
datlist <- miceadds::mids2datlist(imp)

# linear regression with cluster robust standard errors
mod <- lapply(
  datlist, 
  function (dat) {
    estimatr::lm_robust(read ~ paredu + female, dat, clusters = idschool)
  }
)

# subset
mod <- lapply(
  datlist, 
  function (dat) {
    estimatr::lm_robust(read ~ paredu + female, dat, clusters = idschool, subset = urban == 1)
  }
)

# weights
mod <- lapply(
  datlist, 
  function (dat) {
    estimatr::lm_robust(read ~ paredu + female, dat, clusters = idschool, weights = studwgt)
  }
)

# note that you can use the `se_type` argument of lm_robust() 
# to change the vcov estimation

# extract parameters and covariance matrix
betas <- lapply(mod, coef)
vars <- lapply(mod, vcov)
# conduct statistical inference
summary(pool_mi( qhat = betas, u = vars ))
1
votes

I'm no expert, but there is an issue with the passing of the weights to lm(). I know this is not an ideal situation, but I managed to get it to work by modifying the lm.cluster() function to hard code the weights pass and then just used my own.

lm.cluster <- function (data, formula, cluster, wgts=NULL, ...) 
{
  TAM::require_namespace_msg("multiwayvcov")
  if(is.null(wgts)) {
    mod <- stats::lm(data = data, formula = formula)
  } else {
    data$.weights <- wgts
    mod <- stats::lm(data = data, formula = formula, weights=data$.weights)
  }
  if (length(cluster) > 1) {
    v1 <- cluster
  }
  else {
    v1 <- data[, cluster]
  }
  dfr <- data.frame(cluster = v1)
  vcov2 <- multiwayvcov::cluster.vcov(model = mod, cluster = dfr)
  res <- list(lm_res = mod, vcov = vcov2)
  class(res) <- "lm.cluster"
  return(res)
}