--- title: "For SAS users: reproducing PROC MIXED and PROC MI conventions" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{For SAS users: reproducing PROC MIXED and PROC MI conventions} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} knitr::opts_chunk$set(collapse = TRUE, comment = "#>") ``` The package was built by porting a SAS robustness package and validating every cell against it. The conventions below are what it took to agree with `PROC MIXED` and `PROC MI` to the sixth decimal. | SAS | ballast setting | Note | |---|---|---| | `REPEATED visit / SUBJECT=id TYPE=UN` | `covariance = "us"` | `ARH(1)` is `"ar1h"`, `AR(1)` `"ar1"`, `CS` `"cs"`, `CSH` `"csh"`, `TOEP` `"toep"`, `TOEPH` `"toeph"` | | `DDFM=SATTERTHWAITE` | `method = "Satterthwaite", vcov = "Asymptotic"` | | | `DDFM=KR` (the default KR, not KR2) | `method = "Kenward-Roger", vcov = "Kenward-Roger-Linear"` | mmrm's full Kenward-Roger vcov gives a smaller standard error than SAS | | `EMPIRICAL` with any `DDFM` | `method = "Between-Within", vcov = "Empirical"` | SAS cannot combine the sandwich with Satterthwaite or KR and falls back to between-within degrees of freedom; with `sas_conventions = TRUE` the df is computed as observations minus subjects minus the rank of the within-subject design columns | | `LSMEANS trt*visit / DIFF` | `weights = "equal"` | class covariates at equal weights over their levels, continuous covariates at their means | | `LSMEANS ... OBSMARGINS` | `weights = "observed"` | the design averaged over the analysis rows | | `LSMEANS ... AT x = value` | `stress_fit(spec, at = list(x = value))` | | | AICC in the fit statistics | the `aicc` column | the SAS REML definition: `-2 res. log lik + 2 d n* / (n* - d - 1)`, d covariance parameters, n* = N minus the rank of X | | a `CLASS` variable with one level in a subset | dropped with a note | PROC MIXED zeroes the column; R refuses a one-level factor | | `PROC MI ... FCS REG` | `stress_tipping()` | the regression method with a preliminary monotone fill and burn-in iterations | | `MNAR ADJUST(... SHIFT=delta ADJUSTOBS=(trt='active'))` under FCS | `stress_tipping(deltas = ..., shift_every = TRUE)` | SAS adds the shift at every draw, so it propagates through later imputed visits; applying it only to the final draw gives a curve that declines markedly more slowly | | `PROC MIANALYZE` without `EDF=` | Rubin's rules in `mi_pool` | the pooled degrees of freedom can run into the hundreds of thousands when the between-imputation variance is tiny | | `MODELOBS=` (copy reference as a monotone regression) | `stress_reference(methods = "CR")` | the package uses the multivariate-normal formulation of Carpenter, Roger and Kenward, validated against rbmi | ## A spec in SAS terms ```{r spec, eval = FALSE} library(ballast) # PROC MIXED; CLASS usubjid avisitn trtpn cohort site; MODEL pchg = base avisitn trtpn trtpn*avisitn cohort site / DDFM=SATTERTHWAITE; # REPEATED avisitn / SUBJECT=usubjid TYPE=ARH(1); LSMEANS trtpn*avisitn / DIFF; spec <- stress_spec(adeff, response = "pchg", subject = "usubjid", visit = "avisitn", treatment = "trtpn", reference = "1", covariates = ~ base + cohort + site, contrast_visit = "7", covariance = "ar1h", method = "Satterthwaite", vcov = "Asymptotic") ``` Visit as a factor must carry the visit order in its levels; `stress_spec_adam()` orders by `AVISITN`. ## Things that do not reproduce exactly Random-number-based methods (multiple imputation, re-randomisation tests, MM-type robust regression) agree with SAS within Monte Carlo error only; the package reports the Monte Carlo standard error in the row's `note`. A spatial power covariance over days needs the time variable rescaled (days divided by 100, say) before mmrm converges; it is not among the structures the spec accepts.