Skip to content

Add modelling the baseline hazard in the weight models as a flexible function of time - #61

Merged
remlapmot merged 9 commits into
mainfrom
devel-2026-09-21
Sep 22, 2026
Merged

remlapmot merged 9 commits into
mainfrom
devel-2026-09-21

Conversation

@remlapmot

Copy link
Copy Markdown
Contributor

This adds the last PR which went into SEQTaRget - modelling the baseline hazard in the weight model as a flexible function of time by adding an opt-in weight_spline option to SEQopts().

When enabled, the default weight models use natural cubic splines of the time terms in place of the quadratics - followup/followup_sq and trial/trial_sq when weight_preexpansion=False, the time column and its square when weight_preexpansion=True - with knots fixed from the data the models are fit on so the basis is identical across bootstrap resamples. This covers the treatment weight models and, where specified, the cense and visit models. The default is unchanged (weight_spline=False), and the option is the weight-model counterpart of followup_spline.

Also,

  • generalises knot baking to every cr(x, df=N) term in the outcome and weight model formulas rather than just the followup_spline one
  • validates formula argument types in SEQopts()

remlapmot and others added 6 commits September 21, 2026 12:10
…ight models

Add opt-in weight_spline and weight_spline_df to SEQopts, replacing the time quadratics in the default weight models with a natural cubic spline basis. Generalise spline knot baking to every cr(x, df=N) term in the outcome and weight model formulas, so the basis is constant across bootstrap resamples and survives the glum backend's formula re-parse on unpickle. Validate formula argument types in SEQopts, and read column names out of function-call terms in _col_string.
…="center"

Neither warning the weight-spline tests emit marks a bad fit, so filter them at module level with the reasoning. "separation detected" is a false positive of _check_separation's |coef| > 25 rule: the last cr() basis column has a small numeric scale, so its coefficient is legitimately large (~62 with a standard error of ~35, i.e. z ~ 1.8) and every weight model converges. "failed to converge" comes only from the tests that hand-write an unconstrained cr(x, df=N), whose basis spans the constant function and is therefore collinear with the model intercept by one dimension; statsmodels reports the redundancy and pinv resolves it. Since the terms weight_spline generates are centred and avoid this entirely, tell users writing their own cr() terms to pass constraints="center" too - statsmodels only limps through without it and the glum backend cannot fit at all. Also correct the interior knot count in the vignette, which the centring changed from 2 to 3.
@remlapmot
remlapmot requested a review from ryan-odea September 21, 2026 13:03

@ryan-odea ryan-odea left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks good! I shortened the SEQopts comments a bit - hoping its less for an end-user to chew through.

@remlapmot

Copy link
Copy Markdown
Contributor Author

Thanks Ryan

@remlapmot
remlapmot merged commit 6e3cc7b into main Sep 22, 2026
6 checks passed
@remlapmot
remlapmot deleted the devel-2026-09-21 branch September 22, 2026 12:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants