Summary
Any stratified censored VPC fails, because the observed data used on that path is as.data.frame(fit), which does not carry the covariates you would stratify by.
Reproducer
names(fit$origData)
#> "ID" "TIME" "DV" "AMT" "EVID" "CMT" "WT" "cens"
names(as.data.frame(fit))
#> "ID" "TIME" "DV" "EPRED" ... "tad" "dosenum" # no WT
vpcCens(fit, cens = TRUE, n = 5, stratify = "WT")
#> Error: The following specified stratification columns were NOT found in
#> observation data:
#> WT
The uncensored path stratifies fine on the same fit, because it keeps .obs from .vpcUiSetupObservationData() (i.e. origData, which has WT).
Root cause
R/vpcPlot.R, censored branch:
.obs <- as.data.frame(fit)
as.data.frame(fit) returns the fit table (residuals, IPRED, CWRES, tad, ...) and drops the input covariates, so vpc::vpc_cens()'s check_stratification_columns_available() rejects any covariate stratification.
Note the simulated side is fine: nlmixr2est::vpcSimExpand() merges the stratify columns into .sim under the observed names. It is only the observed side that loses them.
Suggested fix
Same underlying decision as #55 - the censored path should build its observed data from the same source as the uncensored path, or carry the stratify columns across explicitly (merging on row numbers, since as.data.frame(fit) and the EVID == 0 subset of origData are equal in length but not guaranteed aligned).
Context
Pre-existing; verified identical on main (52cdc18) and on the #54 branch. Found while reviewing #54.
Related: nlmixr2/nlmixr2est#830 - passing a stratify column that is not in the data triggers a separate failure with a confusing message, because vpcSimExpand() then merges the entire observed dataset into the simulation.
Summary
Any stratified censored VPC fails, because the observed data used on that path is
as.data.frame(fit), which does not carry the covariates you would stratify by.Reproducer
The uncensored path stratifies fine on the same fit, because it keeps
.obsfrom.vpcUiSetupObservationData()(i.e.origData, which hasWT).Root cause
R/vpcPlot.R, censored branch:as.data.frame(fit)returns the fit table (residuals,IPRED,CWRES,tad, ...) and drops the input covariates, sovpc::vpc_cens()'scheck_stratification_columns_available()rejects any covariate stratification.Note the simulated side is fine:
nlmixr2est::vpcSimExpand()merges the stratify columns into.simunder the observed names. It is only the observed side that loses them.Suggested fix
Same underlying decision as #55 - the censored path should build its observed data from the same source as the uncensored path, or carry the stratify columns across explicitly (merging on row numbers, since
as.data.frame(fit)and theEVID == 0subset oforigDataare equal in length but not guaranteed aligned).Context
Pre-existing; verified identical on
main(52cdc18) and on the #54 branch. Found while reviewing #54.Related: nlmixr2/nlmixr2est#830 - passing a stratify column that is not in the data triggers a separate failure with a confusing message, because
vpcSimExpand()then merges the entire observed dataset into the simulation.