mimar: Compact Multiple Imputation, Assessment, and Reporting in R

Artificial amputation, chained-equations MI with ML imputers, diagnostic evaluation, and pooling, in one package

Imad El Badisy

2025-08-15

Missing data is the rule, not the exception, in health research. Yet most workflows still string together three or four packages: one to characterize missingness, one to impute, one to pool, one to evaluate, with no consistent API across them. mimar brings all of that under one roof.

What is mimar?

mimar (v0.8.0) covers the full missing-data analysis cycle:

  1. Amputation: artificially introduce missingness into a complete dataset for simulation studies
  2. Imputation: single or multiple imputation via chained equations with a choice of statistical or ML imputers
  3. Evaluation: diagnostic metrics comparing imputed distributions to observed and (when known) true values
  4. Pooling: Rubin’s rules applied to post-imputation model estimates

Install:

install.packages("mimar")

Artificial amputation

ampute() introduces controlled missingness into a complete data frame, specifying the mechanism (MCAR, MAR, MNAR) and the proportion of missing cells:

library(mimar)

set.seed(1)
amp <- ampute(iris, prop = 0.25, mechanism = "MCAR")

head(amp$data)       # the amputed data frame
# A tibble: 6 × 5
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
         <dbl>       <dbl>        <dbl>       <dbl> <fct>  
1          5.1         3.5          1.4         0.2 setosa 
2          4.9         3           NA           0.2 setosa 
3          4.7         3.2          1.3         0.2 <NA>   
4          4.6         3.1          1.5        NA   setosa 
5         NA           3.6          1.4        NA   setosa 
6          5.4        NA            1.7         0.4 setosa 

Multiple imputation

impute() runs chained equations with any registered imputer. The default is predictive mean matching ("pmm"), but ML-based imputers are equally accessible:

# PMM: the safe default
imp_pmm <- impute(amp, m = 5, imputer = "pmm", maxit = 5)

# Random forest imputation
imp_rf <- impute(amp, m = 5, imputer = "ranger")

# XGBoost imputation
imp_xgb <- impute(amp, m = 5, imputer = "xgboost")

class(imp_pmm)
[1] "mimar_imputation" "list"            

impute() returns a mimar_imputation object containing all m completed datasets alongside metadata for downstream steps.

Available imputers

imputer_registry()[, c("imputer", "implementation", "stochastic")]
# A tibble: 23 × 3
   imputer implementation stochastic
   <chr>   <chr>          <lgl>     
 1 mean    mimar          FALSE     
 2 median  mimar          FALSE     
 3 mode    mimar          FALSE     
 4 naive   mimar          FALSE     
 5 norm    mimar          TRUE      
 6 pmm     mimar          TRUE      
 7 spmm    mimar          TRUE      
 8 logreg  mimar          TRUE      
 9 polyreg mimar          TRUE      
10 rf      wrapped        TRUE      
# ℹ 13 more rows

Evaluation

When the true values are known (after amputation, or from a simulation), evaluate() computes recovery metrics comparing imputed to true values:

diag <- evaluate(imp_pmm)
diag$distribution       # observed vs. imputed means, SDs, unique counts
# A tibble: 5 × 9
  variable     type    missing observed_unique imputed_unique observed_mean
  <chr>        <chr>     <int>           <int>          <int>         <dbl>
1 Sepal.Length numeric      33              33             29          5.84
2 Sepal.Width  numeric      39              22             19          3.08
3 Petal.Length numeric      34              42             36          3.76
4 Petal.Width  numeric      34              21             21          1.25
5 Species      factor       31               3              3         NA   
# ℹ 3 more variables: imputed_mean <dbl>, observed_sd <dbl>, imputed_sd <dbl>

Completing and pooling

Extract a single completed dataset or pool regression estimates across all m imputations using Rubin’s rules:

completed <- complete(imp_pmm, which = 1)
head(completed)
# A tibble: 6 × 5
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
         <dbl>       <dbl>        <dbl>       <dbl> <fct>  
1          5.1         3.5          1.4         0.2 setosa 
2          4.9         3            1.4         0.2 setosa 
3          4.7         3.2          1.3         0.2 setosa 
4          4.6         3.1          1.5         0.2 setosa 
5          5.1         3.6          1.4         0.5 setosa 
6          5.4         3.3          1.7         0.4 setosa 
# fit a model on each completed dataset, then pool the coefficients
completed_list <- lapply(seq_len(imp_pmm$m), function(k) complete(imp_pmm, which = k))
fits  <- lapply(completed_list, function(d) lm(Sepal.Length ~ Sepal.Width + Petal.Length + Petal.Width, data = d))
betas <- lapply(fits, coef)
vars  <- lapply(fits, function(f) diag(vcov(f)))

pool(betas, variance = vars)
mimar pooled results
# A tibble: 4 × 14
  term      estimate std.error statistic    df  p.value conf.low conf.high     m
  <chr>        <dbl>     <dbl>     <dbl> <dbl>    <dbl>    <dbl>     <dbl> <int>
1 (Interce…    2.01     0.246       8.17   Inf 3.04e-16    1.53      2.49      5
2 Sepal.Wi…    0.610    0.0646      9.43   Inf 4.00e-21    0.483     0.736     5
3 Petal.Le…    0.735    0.0614     12.0    Inf 4.90e-33    0.614     0.855     5
4 Petal.Wi…   -0.638    0.136      -4.71   Inf 2.49e- 6   -0.904    -0.373     5
# ℹ 5 more variables: within_variance <dbl>, between_variance <dbl>,
#   total_variance <dbl>, relative_increase_variance <dbl>, rule <chr>

When to use mimar

mimar is designed for: