DeclareDesign / estimatr

estimatr: Fast Estimators for Design-Based Inference
https://declaredesign.org/r/estimatr
Other
131 stars 20 forks source link

Provide model data like lm's model$model #374

Closed dfrankow closed 3 years ago

dfrankow commented 3 years ago

This is a feature request.

It would be useful if the results returned from lm_robust could have the data the model was built on. Could be an optional flag.

Example:

library(datasets)

> model <- lm(mpg ~ cyl, data=mtcars)
> nrow(model$model)
[1] 32
> model2 <- estimatr::lm_robust(mpg ~ cyl, data=mtcars)
> nrow(model2$model)
NULL

I wrote the following function to hack around the lack of this feature.

#' Reconstruct model data from dat and model.
#'
#' This is to construct data for lm_robust equivalent to lm's model$model
#' NOTE: drops rows with any NA, as lm doesn't use them.
#' Only reconstructs the data, not all the attributes of model$model.
#'
#' @param dat  Data frame
#' @param model  Model from lm or lm_robust
reconstruct_model_data <- function(dat, model) {
  the_vars <- as.list(attr(terms(model), "variables"))
  # drop first element, which is "list"
  stopifnot(as.character(the_vars[[1]]) == "list")
  the_vars[[1]] <- NULL
  the_vars <- as.character(the_vars)
  # subset vars
  stopifnot(all(the_vars %in% names(dat)))
  dat <- dat[,the_vars]
  # drop NAs in the subset
  dat[complete.cases(dat),]
}

Example usage:

> nrow(reconstruct_model_data(mtcars, model2))
[1] 32

It really only matters in the face of NAs, but that's an important use case.

nfultz commented 3 years ago

Generally it's better to go through the corresponding accessor methods, in this case model.frame, rather than digging into the object internals.

> m <- estimatr::lm_robust(mpg ~ cyl, data=mtcars)
> nrow(model.frame(m))
[1] 32
dfrankow commented 3 years ago

Oh great!

Yeah, it's not always clear to me what's internal and what's not.

If that's always available, then it might be enough for me.

In some cases, I have had problems with the data object going out of scope, while I wish the model would hang onto it.

However, you can close this issue, and I can re-open if I have a reproducible issue.

dfrankow commented 3 years ago

Or I can close it. :)