---
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.
