bossanova 0.1.0.dev18__tar.gz → 0.1.0.dev19__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/PKG-INFO +1 -1
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/__init__.py +4 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/data/__init__.py +18 -2
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/expressions.py +11 -11
- bossanova-0.1.0.dev19/bossanova/internal/compare/__init__.py +12 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/containers/structs/display.py +44 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/design/__init__.py +0 -6
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/fit/__init__.py +0 -23
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/formula/__init__.py +0 -19
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/infer/__init__.py +0 -23
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/infer/dispatch.py +9 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/marginal/__init__.py +2 -13
- bossanova-0.1.0.dev19/bossanova/internal/rendering/__init__.py +22 -0
- bossanova-0.1.0.dev19/bossanova/internal/rendering/markdown.py +163 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/simulation/__init__.py +0 -12
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/viz/mem.py +4 -5
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/viz/predict.py +14 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/model/core.py +229 -182
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/model/result.py +84 -0
- bossanova-0.1.0.dev19/bossanova/model/summary.py +1103 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/pyproject.toml +6 -2
- bossanova-0.1.0.dev18/bossanova/internal/compare/__init__.py +0 -27
- bossanova-0.1.0.dev18/bossanova/internal/rendering/__init__.py +0 -16
- bossanova-0.1.0.dev18/bossanova/model/summary.py +0 -467
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/.gitignore +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/LICENSE +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/README.md +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/data/README.md +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/data/advertising.csv +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/data/cake.csv +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/data/chickweight.csv +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/data/credit.csv +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/data/gammas.csv +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/data/mtcars.csv +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/data/penguins.csv +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/data/poker.csv +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/data/sleep.csv +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/data/titanic.csv +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/data/titanic_test.csv +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/data/titanic_train.csv +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/distributions/__init__.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/distributions/continuous.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/distributions/discrete.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/distributions/varying.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/__init__.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/compare/compare.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/compare/cv.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/compare/deviance.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/compare/f_test.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/compare/helpers.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/compare/ic.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/compare/lrt.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/compare/lrt_compare.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/compare/refit.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/containers/__init__.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/containers/builders/__init__.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/containers/builders/dataframes.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/containers/builders/resamples.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/containers/builders/results.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/containers/builders/specs.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/containers/builders/state.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/containers/schemas.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/containers/structs/__init__.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/containers/structs/data.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/containers/structs/explore.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/containers/structs/formula.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/containers/structs/specs.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/containers/structs/state.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/containers/validators.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/design/coding.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/design/names.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/design/reference.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/design/z_matrix.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/fit/convergence.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/fit/diagnostics.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/fit/dispatch.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/fit/glm.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/fit/glmer.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/fit/lmer.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/fit/ols.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/fit/predict.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/fit/rank.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/fit/varying.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/formula/bundle.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/formula/contrast_registry.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/formula/contrast_specs.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/formula/design.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/formula/encoding.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/formula/evaluate.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/formula/evaluate_contrast.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/formula/evaluate_newdata.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/formula/evaluate_transforms.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/formula/helpers.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/formula/parse.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/formula/parser/__init__.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/formula/parser/expr.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/formula/parser/parser.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/formula/parser/scanner.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/formula/parser/token.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/formula/random_effects.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/infer/asymptotic.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/infer/bootstrap.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/infer/cv.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/infer/formula_utils.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/infer/mee.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/infer/params.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/infer/permutation.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/infer/prediction.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/infer/profile.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/infer/resample/__init__.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/infer/resample/common.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/infer/resample/core.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/infer/resample/glmer.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/infer/resample/lm_operators.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/infer/resample/lmer.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/infer/resample/results.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/infer/resample/simulate.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/infer/resample_bundle.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/infer/satterthwaite_emm.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/infer/simulation.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/marginal/bracket_contrasts.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/marginal/compute.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/marginal/conditions.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/marginal/contrasts.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/marginal/emm.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/marginal/explore.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/marginal/explore_parser.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/marginal/explore_scanner.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/marginal/factors.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/marginal/grid.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/marginal/inference.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/marginal/joint_tests.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/marginal/matrices.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/marginal/slopes.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/marginal/transforms.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/marginal/validation.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/__init__.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/backend/__init__.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/backend/dispatch.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/backend/jax.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/backend/numpy.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/backend/protocol.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/batching.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/config.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/convergence.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/differentiation.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/distributions/__init__.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/distributions/algebra.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/distributions/base.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/distributions/core.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/distributions/derived.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/distributions/factories.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/distributions/plotting.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/distributions/probability.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/family/__init__.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/family/binomial.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/family/create.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/family/gamma.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/family/gaussian.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/family/links.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/family/poisson.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/family/response.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/family/schema.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/family/tdist.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/inference/__init__.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/inference/diagnostics.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/inference/estimation.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/inference/hypothesis.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/inference/information_criteria.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/inference/multiplicity.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/inference/profile.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/inference/sandwich.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/inference/satterthwaite.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/inference/wald_variance.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/inference/welch.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/linalg/__init__.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/linalg/qr.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/linalg/schur.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/linalg/sparse.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/linalg/svd.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/predict.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/rng.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/rounding.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/solvers/__init__.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/solvers/glm.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/solvers/glmer.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/solvers/heuristics.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/solvers/initialization.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/solvers/lambda_builder.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/solvers/lambda_sparse.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/solvers/lambda_template.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/solvers/lmer.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/solvers/optimize.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/solvers/pirls_sparse.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/solvers/quadrature.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/tolerances.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/transforms.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/variance.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/maths/weights.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/rendering/latex.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/simulation/dgp/__init__.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/simulation/dgp/generate.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/simulation/dgp/glm.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/simulation/dgp/glmer.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/simulation/dgp/lm.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/simulation/dgp/lmer.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/simulation/harness.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/simulation/metrics.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/simulation/model_sim.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/simulation/power.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/viz/README.md +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/viz/__init__.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/viz/cognition.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/viz/compare.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/viz/core.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/viz/core_data.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/viz/core_protocols.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/viz/core_sizing.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/viz/core_viz.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/viz/dag.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/viz/design.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/viz/fit.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/viz/fit_builders.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/viz/fit_layers.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/viz/helpers.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/viz/lattice.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/viz/layout.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/viz/mem_forest.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/viz/params.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/viz/profile.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/viz/ranef.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/viz/relationships.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/viz/resamples.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/viz/resid.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/viz/vif.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/model/__init__.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/model/guards.py +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/py.typed +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/tests/bossanova_benchmarks/bootstrap/data/README.md +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/tests/bossanova_benchmarks/insteval/data/README.md +0 -0
- {bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/tests/bossanova_tests/hypothesis/README.md +0 -0
|
@@ -36,6 +36,9 @@ from bossanova.internal.compare import compare, lrt # noqa: E402
|
|
|
36
36
|
# Visualization
|
|
37
37
|
from bossanova.internal import viz # noqa: E402
|
|
38
38
|
|
|
39
|
+
# Export utilities
|
|
40
|
+
from bossanova.internal.rendering.markdown import to_markdown # noqa: E402
|
|
41
|
+
|
|
39
42
|
# Expressions
|
|
40
43
|
from bossanova import expressions # noqa: E402
|
|
41
44
|
|
|
@@ -53,6 +56,7 @@ __all__ = [
|
|
|
53
56
|
"set_display_digits",
|
|
54
57
|
"set_singular_tolerance",
|
|
55
58
|
"show_datasets",
|
|
59
|
+
"to_markdown",
|
|
56
60
|
"viz",
|
|
57
61
|
]
|
|
58
62
|
|
|
@@ -1,4 +1,20 @@
|
|
|
1
|
-
"""Bundled sample datasets for regression and mixed-effects modeling.
|
|
1
|
+
"""Bundled sample datasets for regression and mixed-effects modeling.
|
|
2
|
+
|
|
3
|
+
| Dataset | Argument | Description |
|
|
4
|
+
|---------|----------|-------------|
|
|
5
|
+
| Advertising | `"advertising"` | TV, radio, newspaper ad spend vs sales (200 x 4) |
|
|
6
|
+
| Cake | `"cake"` | Baking angle by recipe and temperature (270 x 5) |
|
|
7
|
+
| ChickWeight | `"chickweight"` | Chick weight over time by diet (578 x 4) |
|
|
8
|
+
| Credit | `"credit"` | Credit card balance by income and demographics (400 x 11) |
|
|
9
|
+
| Gammas | `"gammas"` | Simulated BOLD signal for Gamma GLM (6000 x 4) |
|
|
10
|
+
| mtcars | `"mtcars"` | Motor Trend car road tests (32 x 12) |
|
|
11
|
+
| Penguins | `"penguins"` | Palmer Penguins body measurements (344 x 8) |
|
|
12
|
+
| Poker | `"poker"` | Poker hand outcomes by skill and limit (300 x 4) |
|
|
13
|
+
| Sleep | `"sleep"` | Reaction time vs sleep deprivation (180 x 3) |
|
|
14
|
+
| Titanic | `"titanic"` | Passenger survival with demographics (891 x 15) |
|
|
15
|
+
| Titanic Train | `"titanic_train"` | Titanic training set, Kaggle format (891 x 12) |
|
|
16
|
+
| Titanic Test | `"titanic_test"` | Titanic test set, Kaggle format (418 x 11) |
|
|
17
|
+
"""
|
|
2
18
|
|
|
3
19
|
from importlib.resources import files
|
|
4
20
|
from typing import Literal
|
|
@@ -52,7 +68,7 @@ def show_datasets() -> pl.DataFrame:
|
|
|
52
68
|
```python
|
|
53
69
|
from bossanova.data import show_datasets
|
|
54
70
|
show_datasets()
|
|
55
|
-
# shape: (
|
|
71
|
+
# shape: (12, 2)
|
|
56
72
|
# ┌───────────────┬─────────────────────────────────┐
|
|
57
73
|
# │ name ┆ description │
|
|
58
74
|
# │ --- ┆ --- │
|
|
@@ -4,17 +4,17 @@ This module provides stateless Polars expressions for data transformations
|
|
|
4
4
|
commonly used in statistical modeling. These match the semantics of the
|
|
5
5
|
formula-based transforms in `bossanova.internal.formula`.
|
|
6
6
|
|
|
7
|
-
Core Transforms
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
Additional Helpers
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
7
|
+
**Core Transforms:**
|
|
8
|
+
- `center(col)` — subtract mean only
|
|
9
|
+
- `norm(col)` — divide by std only
|
|
10
|
+
- `zscore(col)` — traditional z-score (1 SD)
|
|
11
|
+
- `scale(col)` — Gelman scaling (2 SD)
|
|
12
|
+
|
|
13
|
+
**Additional Helpers:**
|
|
14
|
+
- `rank(col, method)` — average-method rank transform
|
|
15
|
+
- `winsorize(col, lower, upper)` — percentile capping
|
|
16
|
+
- `lag(col, n)` — lagged values
|
|
17
|
+
- `lead(col, n)` — lead values
|
|
18
18
|
|
|
19
19
|
The scale() transform follows Gelman (2008) recommendation to divide by
|
|
20
20
|
2 standard deviations, making continuous predictor coefficients directly
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""Model comparison: information criteria, likelihood ratio tests, and composite tables.
|
|
2
|
+
|
|
3
|
+
Call chain:
|
|
4
|
+
bossanova.compare(m1, m2, ...) -> compare() (composite AIC/BIC/loglik table)
|
|
5
|
+
bossanova.lrt(m1, m2) -> lrt() (nested model likelihood ratio test)
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from bossanova.internal.compare.compare import compare
|
|
9
|
+
from bossanova.internal.compare.ic import compare_aic, compare_bic
|
|
10
|
+
from bossanova.internal.compare.lrt import lrt
|
|
11
|
+
|
|
12
|
+
__all__ = ["compare", "compare_aic", "compare_bic", "lrt"]
|
{bossanova-0.1.0.dev18 → bossanova-0.1.0.dev19}/bossanova/internal/containers/structs/display.py
RENAMED
|
@@ -101,3 +101,47 @@ class MathDisplay:
|
|
|
101
101
|
LaTeX equation without $$ delimiters.
|
|
102
102
|
"""
|
|
103
103
|
return self.equation
|
|
104
|
+
|
|
105
|
+
def to_markdown(
|
|
106
|
+
self,
|
|
107
|
+
path: str | None = None,
|
|
108
|
+
*,
|
|
109
|
+
include_explanations: bool = True,
|
|
110
|
+
) -> str:
|
|
111
|
+
"""Export equation as Quarto-compatible display math markdown.
|
|
112
|
+
|
|
113
|
+
Wraps the equation in ``$$...$$`` display math delimiters. When
|
|
114
|
+
*include_explanations* is True, appends the term explanations as
|
|
115
|
+
a bulleted list below the equation block.
|
|
116
|
+
|
|
117
|
+
Suitable for embedding in ``.qmd`` files via Quarto's
|
|
118
|
+
``{{< include >}}`` shortcode.
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
path: Optional file path to write the markdown. Parent
|
|
122
|
+
directories are created automatically. If None, returns
|
|
123
|
+
the string without writing.
|
|
124
|
+
include_explanations: If True (default), append term
|
|
125
|
+
explanations below the equation.
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
Markdown string with ``$$equation$$`` and optional
|
|
129
|
+
explanations.
|
|
130
|
+
|
|
131
|
+
Examples:
|
|
132
|
+
>>> m.show_math().to_markdown("equations/model_eq.md")
|
|
133
|
+
>>> md = m.show_math().to_markdown(include_explanations=False)
|
|
134
|
+
"""
|
|
135
|
+
from bossanova.internal.rendering.markdown import (
|
|
136
|
+
equation_to_markdown,
|
|
137
|
+
write_text,
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
text = equation_to_markdown(
|
|
141
|
+
self.equation,
|
|
142
|
+
self.explanations,
|
|
143
|
+
include_explanations=include_explanations,
|
|
144
|
+
)
|
|
145
|
+
if path is not None:
|
|
146
|
+
write_text(text, path)
|
|
147
|
+
return text
|
|
@@ -4,12 +4,6 @@ Call chain:
|
|
|
4
4
|
formula.build_design_matrices() -> treatment_coding() / sum_coding() / ... (categorical columns)
|
|
5
5
|
marginal.build_reference_grid() -> build_reference_row() (EMM reference grids)
|
|
6
6
|
formula.build_random_effects_from_spec() -> build_z_simple() / build_z_nested() / build_z_crossed()
|
|
7
|
-
|
|
8
|
-
Submodules:
|
|
9
|
-
coding: Contrast matrix builders for categorical encoding (treatment, sum, helmert, poly)
|
|
10
|
-
names: Design matrix column name parsing and variable type detection
|
|
11
|
-
reference: Reference design matrix (X_ref) for marginal effects
|
|
12
|
-
z_matrix: Sparse Z matrix (random effects design matrix) construction
|
|
13
7
|
"""
|
|
14
8
|
|
|
15
9
|
from .coding import (
|
|
@@ -2,29 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
Call chain:
|
|
4
4
|
model.fit() -> fit_model() -> resolve_solver() -> fit_ols_qr / fit_glm_irls / fit_lmer_pls / fit_glmer_pirls
|
|
5
|
-
|
|
6
|
-
Container flow:
|
|
7
|
-
Input: ModelSpec, DataBundle
|
|
8
|
-
Output: FitState (coef, vcov, fitted, residuals, loglik, theta for mixed)
|
|
9
|
-
|
|
10
|
-
Solver dispatch:
|
|
11
|
-
gaussian + no RE -> fit_ols_qr (QR decomposition)
|
|
12
|
-
gaussian + no RE -> fit_glm_irls (if method="ml")
|
|
13
|
-
non-gauss + no RE -> fit_glm_irls (IRLS)
|
|
14
|
-
gaussian + RE -> fit_lmer_pls (Penalized Least Squares)
|
|
15
|
-
non-gauss + RE -> fit_glmer_pirls (Penalized IRLS)
|
|
16
|
-
|
|
17
|
-
Submodules:
|
|
18
|
-
dispatch: Solver selection and fit_model entry point
|
|
19
|
-
ols: QR decomposition fitting (OLS/WLS)
|
|
20
|
-
glm: Iteratively Reweighted Least Squares (IRLS)
|
|
21
|
-
lmer: Penalized Least Squares (PLS) for LMM
|
|
22
|
-
glmer: Penalized IRLS (PIRLS) for GLMM
|
|
23
|
-
rank: Rank deficiency detection via pivoted QR
|
|
24
|
-
diagnostics: AIC/BIC, R-squared, metadata computation
|
|
25
|
-
convergence: Mixed model convergence checks (gradient, Hessian)
|
|
26
|
-
varying: BLUP extraction and variance component decomposition
|
|
27
|
-
predict: Prediction on training or new data
|
|
28
5
|
"""
|
|
29
6
|
|
|
30
7
|
from bossanova.internal.fit.convergence import check_convergence
|
|
@@ -3,25 +3,6 @@
|
|
|
3
3
|
Call chain:
|
|
4
4
|
model(formula, data) -> parse_formula() -> build_bundle_from_data() -> build_design_matrices()
|
|
5
5
|
model.predict(newdata=) -> evaluate_newdata() (applies learned encoding to new observations)
|
|
6
|
-
|
|
7
|
-
Container flow:
|
|
8
|
-
Input: formula string + Polars DataFrame
|
|
9
|
-
Output: FormulaSpec (via parse_formula) + DataBundle (X, y, Z matrices via build_design_matrices)
|
|
10
|
-
|
|
11
|
-
Submodules:
|
|
12
|
-
parse: R-style formula string parsing into FormulaSpec
|
|
13
|
-
parser/: Recursive descent parser (scanner, tokens, AST nodes)
|
|
14
|
-
design: Design matrix construction from FormulaSpec
|
|
15
|
-
evaluate: Term evaluation (AST nodes to design matrix columns)
|
|
16
|
-
evaluate_transforms: Stateful, math, and polynomial transforms
|
|
17
|
-
evaluate_contrast: Contrast function evaluation for categorical encoding
|
|
18
|
-
evaluate_newdata: Apply learned encoding to new observations
|
|
19
|
-
encoding: Categorical variable encoding using Polars Enum
|
|
20
|
-
random_effects: Z matrix construction from FormulaSpec
|
|
21
|
-
helpers: Shared AST utilities
|
|
22
|
-
bundle: DataBundle construction from formula + DataFrame
|
|
23
|
-
contrast_registry: Contrast function vocabulary and validation
|
|
24
|
-
contrast_specs: User-facing contrast specification resolution
|
|
25
6
|
"""
|
|
26
7
|
|
|
27
8
|
from bossanova.internal.formula.design import (
|
|
@@ -1,31 +1,8 @@
|
|
|
1
1
|
"""Inference operations: asymptotic, bootstrap, permutation, cross-validation, profile, and simulation.
|
|
2
2
|
|
|
3
|
-
Provides asymptotic (Wald-based), bootstrap, permutation, cross-validation,
|
|
4
|
-
profile likelihood, and simulation inference for parameters, marginal effects,
|
|
5
|
-
predictions, and variance components.
|
|
6
|
-
|
|
7
3
|
Call chain:
|
|
8
4
|
model.infer() -> dispatch_infer() -> dispatch_{params,mee,prediction}_inference()
|
|
9
5
|
Each dispatcher routes to the method-specific backend (asymptotic, bootstrap, etc.)
|
|
10
|
-
|
|
11
|
-
Container flow:
|
|
12
|
-
Input: ModelSpec, DataBundle, FitState (+ MeeState for effects, PredictionState for predictions)
|
|
13
|
-
Output: InferenceState (SE, CI, p-values) augmented onto the target state
|
|
14
|
-
|
|
15
|
-
Submodules:
|
|
16
|
-
dispatch: Top-level infer routing
|
|
17
|
-
params: Parameter inference dispatch
|
|
18
|
-
mee: Marginal effects inference dispatch
|
|
19
|
-
prediction: Prediction inference dispatch
|
|
20
|
-
asymptotic: Wald-based SEs, CIs, p-values
|
|
21
|
-
bootstrap: Parametric and nonparametric bootstrap
|
|
22
|
-
permutation: Permutation tests for params and effects
|
|
23
|
-
cv: K-fold and group-K-fold cross-validation
|
|
24
|
-
profile: Profile likelihood for variance components
|
|
25
|
-
simulation: Summary statistics across simulation replicates
|
|
26
|
-
satterthwaite_emm: Satterthwaite df for EMM contrasts (mixed models)
|
|
27
|
-
resample/: Resampling engine (bootstrap indices, CI methods, model-type hooks)
|
|
28
|
-
formula_utils: Formula manipulation for term ablation (CV)
|
|
29
6
|
"""
|
|
30
7
|
|
|
31
8
|
from bossanova.internal.infer.asymptotic import (
|
|
@@ -189,6 +189,15 @@ def dispatch_infer(
|
|
|
189
189
|
threshold=threshold,
|
|
190
190
|
)
|
|
191
191
|
|
|
192
|
+
# --- CV with stale predict state: reroute to fit branch ---
|
|
193
|
+
# When last_op is "predict" but predictions were made on newdata (different
|
|
194
|
+
# n than training data), CV can't attach training-data-sized arrays to the
|
|
195
|
+
# prediction state. Fall back to the fit branch which produces model-level
|
|
196
|
+
# CV metrics (PRE, RMSE, etc.) — almost always what the user intended.
|
|
197
|
+
if how == "cv" and last_op == "predict" and pred is not None:
|
|
198
|
+
if len(pred.fitted) != bundle.n:
|
|
199
|
+
last_op = "fit"
|
|
200
|
+
|
|
192
201
|
# --- Dispatch based on last_op ---
|
|
193
202
|
match last_op:
|
|
194
203
|
case "fit":
|
|
@@ -1,18 +1,7 @@
|
|
|
1
1
|
"""Marginal effects and estimated marginal means computation.
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
2. EMM/Slopes (compute_emm, compute_slopes): Predictions at grid points
|
|
6
|
-
3. Contrasts (compute_contrasts): Apply contrast matrices to EMM results
|
|
7
|
-
|
|
8
|
-
Provides:
|
|
9
|
-
- parse_explore_formula: Parse explore formula syntax
|
|
10
|
-
- ExploreFormula, ExploreFormulaError, Condition: Parsed explore formula types
|
|
11
|
-
- build_reference_grid: Construct evaluation grid from DataBundle
|
|
12
|
-
- compute_emm: Compute estimated marginal means at grid points
|
|
13
|
-
- compute_slopes: Compute marginal effects for continuous predictors
|
|
14
|
-
- compute_contrasts: Apply contrast matrices to EMM results
|
|
15
|
-
- matrices: EMM contrast matrix builders (build_*_matrix)
|
|
3
|
+
Call chain:
|
|
4
|
+
model.explore() -> build_reference_grid() -> compute_emm() / compute_slopes() -> compute_contrasts()
|
|
16
5
|
"""
|
|
17
6
|
|
|
18
7
|
from bossanova.internal.marginal.explore import (
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""LaTeX equation and markdown rendering for model output.
|
|
2
|
+
|
|
3
|
+
Call chain:
|
|
4
|
+
model.equation() -> build_equation(spec) -> LaTeX string
|
|
5
|
+
model_result.to_markdown() -> dataframe_to_markdown(df) -> markdown string
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from bossanova.internal.rendering.latex import build_equation
|
|
9
|
+
from bossanova.internal.rendering.markdown import (
|
|
10
|
+
dataframe_to_markdown,
|
|
11
|
+
equation_to_markdown,
|
|
12
|
+
to_markdown,
|
|
13
|
+
write_text,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"build_equation",
|
|
18
|
+
"dataframe_to_markdown",
|
|
19
|
+
"equation_to_markdown",
|
|
20
|
+
"to_markdown",
|
|
21
|
+
"write_text",
|
|
22
|
+
]
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"""Markdown table and equation rendering for report export.
|
|
2
|
+
|
|
3
|
+
Pure functions that convert Polars DataFrames and LaTeX equations into
|
|
4
|
+
pipe-delimited GitHub Flavored Markdown / Quarto-compatible text.
|
|
5
|
+
Used by ``ModelResult.to_markdown()``, ``MathDisplay.to_markdown()``,
|
|
6
|
+
and the top-level ``bossanova.to_markdown()`` utility.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
import polars as pl
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"dataframe_to_markdown",
|
|
17
|
+
"equation_to_markdown",
|
|
18
|
+
"to_markdown",
|
|
19
|
+
"write_text",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def dataframe_to_markdown(
|
|
24
|
+
df: pl.DataFrame,
|
|
25
|
+
caption: str | None = None,
|
|
26
|
+
) -> str:
|
|
27
|
+
"""Convert a Polars DataFrame to a pipe-delimited markdown table.
|
|
28
|
+
|
|
29
|
+
Produces GitHub Flavored Markdown (GFM) table syntax that renders
|
|
30
|
+
correctly in Quarto, GitHub, and most markdown environments. Columns
|
|
31
|
+
are padded to align visually. Null values render as empty cells.
|
|
32
|
+
|
|
33
|
+
No additional numeric formatting is applied — the DataFrame is assumed
|
|
34
|
+
to be pre-rounded (as all bossanova result DataFrames are).
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
df: Polars DataFrame to convert.
|
|
38
|
+
caption: Optional table caption. Rendered as ``Table: {caption}``
|
|
39
|
+
above the table (Quarto cross-reference syntax).
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
Pipe-delimited markdown table as a string.
|
|
43
|
+
|
|
44
|
+
Examples:
|
|
45
|
+
>>> import polars as pl
|
|
46
|
+
>>> df = pl.DataFrame({"x": [1, 2], "y": [3.14, 2.72]})
|
|
47
|
+
>>> print(dataframe_to_markdown(df))
|
|
48
|
+
| x | y |
|
|
49
|
+
|---|------|
|
|
50
|
+
| 1 | 3.14 |
|
|
51
|
+
| 2 | 2.72 |
|
|
52
|
+
"""
|
|
53
|
+
cols = df.columns
|
|
54
|
+
|
|
55
|
+
# Convert all values to strings, rendering nulls as empty
|
|
56
|
+
str_rows: list[list[str]] = []
|
|
57
|
+
for row in df.iter_rows():
|
|
58
|
+
str_rows.append([("" if v is None else str(v)) for v in row])
|
|
59
|
+
|
|
60
|
+
# Compute column widths (minimum 3 for the separator dashes)
|
|
61
|
+
widths = [max(3, len(c)) for c in cols]
|
|
62
|
+
for row in str_rows:
|
|
63
|
+
for i, cell in enumerate(row):
|
|
64
|
+
widths[i] = max(widths[i], len(cell))
|
|
65
|
+
|
|
66
|
+
# Build table lines
|
|
67
|
+
header = "| " + " | ".join(c.ljust(widths[i]) for i, c in enumerate(cols)) + " |"
|
|
68
|
+
separator = "|" + "|".join("-" * (w + 2) for w in widths) + "|"
|
|
69
|
+
data_lines = [
|
|
70
|
+
"| " + " | ".join(cell.ljust(widths[i]) for i, cell in enumerate(row)) + " |"
|
|
71
|
+
for row in str_rows
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
parts: list[str] = []
|
|
75
|
+
if caption is not None:
|
|
76
|
+
parts.append(f"Table: {caption}")
|
|
77
|
+
parts.append("")
|
|
78
|
+
parts.append(header)
|
|
79
|
+
parts.append(separator)
|
|
80
|
+
parts.extend(data_lines)
|
|
81
|
+
return "\n".join(parts)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def equation_to_markdown(
|
|
85
|
+
equation: str,
|
|
86
|
+
explanations: tuple[str, ...] = (),
|
|
87
|
+
*,
|
|
88
|
+
include_explanations: bool = True,
|
|
89
|
+
) -> str:
|
|
90
|
+
r"""Wrap a LaTeX equation in display math delimiters for Quarto.
|
|
91
|
+
|
|
92
|
+
Produces ``$$...$$`` display math that Quarto renders natively in
|
|
93
|
+
Typst, HTML, and PDF output. Optionally appends term explanations
|
|
94
|
+
as plain text below the equation block.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
equation: LaTeX equation string (without ``$$`` delimiters).
|
|
98
|
+
explanations: Term explanation strings from ``MathDisplay``.
|
|
99
|
+
include_explanations: If True (default), append explanations
|
|
100
|
+
as plain text lines below the equation.
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
Markdown string with display math block and optional explanations.
|
|
104
|
+
|
|
105
|
+
Examples:
|
|
106
|
+
>>> print(equation_to_markdown(r"y = \beta_0 + \beta_1 x"))
|
|
107
|
+
$$
|
|
108
|
+
y = \beta_0 + \beta_1 x
|
|
109
|
+
$$
|
|
110
|
+
"""
|
|
111
|
+
parts = [f"$$\n{equation}\n$$"]
|
|
112
|
+
if include_explanations and explanations:
|
|
113
|
+
parts.append("")
|
|
114
|
+
for exp in explanations:
|
|
115
|
+
parts.append(f"- {exp}")
|
|
116
|
+
return "\n".join(parts)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def write_text(text: str, path: str | Path) -> None:
|
|
120
|
+
"""Write text content to a file, creating parent directories.
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
path: Destination file path. Parent directories are created
|
|
124
|
+
automatically if they don't exist.
|
|
125
|
+
text: Text content to write.
|
|
126
|
+
"""
|
|
127
|
+
dest = Path(path)
|
|
128
|
+
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
129
|
+
dest.write_text(text, encoding="utf-8")
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def to_markdown(
|
|
133
|
+
df: pl.DataFrame,
|
|
134
|
+
path: str | Path | None = None,
|
|
135
|
+
caption: str | None = None,
|
|
136
|
+
) -> str:
|
|
137
|
+
"""Convert a Polars DataFrame to a markdown table, optionally saving to file.
|
|
138
|
+
|
|
139
|
+
Standalone utility for DataFrames not wrapped in ``ModelResult`` —
|
|
140
|
+
such as results from ``compare()``, ``model.jointtest()``,
|
|
141
|
+
``model.vif()``, ``model.to_odds_ratio()``, etc.
|
|
142
|
+
|
|
143
|
+
For ``ModelResult`` objects (returned by ``.fit()``, ``.infer()``,
|
|
144
|
+
etc.), use ``result.to_markdown()`` instead.
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
df: Polars DataFrame to convert.
|
|
148
|
+
path: Optional file path. If given, writes the markdown and
|
|
149
|
+
creates parent directories automatically.
|
|
150
|
+
caption: Optional table caption (``Table: ...`` Quarto syntax).
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
Pipe-delimited markdown table as a string.
|
|
154
|
+
|
|
155
|
+
Examples:
|
|
156
|
+
>>> from bossanova import compare, to_markdown
|
|
157
|
+
>>> to_markdown(compare(m1, m2), "comparison.md", caption="Model Comparison")
|
|
158
|
+
>>> md = to_markdown(m.jointtest()) # string only
|
|
159
|
+
"""
|
|
160
|
+
text = dataframe_to_markdown(df, caption=caption)
|
|
161
|
+
if path is not None:
|
|
162
|
+
write_text(text, path)
|
|
163
|
+
return text
|
|
@@ -4,18 +4,6 @@ Call chain:
|
|
|
4
4
|
model.simulate(n=...) -> generate_{lm,glm,lmer,glmer}_data() (pre-fit DGP)
|
|
5
5
|
model.simulate(nsim=...) -> simulate_responses_from_fit() (post-fit parametric bootstrap)
|
|
6
6
|
run_power_study(formula, ...) -> run_power_analysis() -> expand_sweep_grid()
|
|
7
|
-
|
|
8
|
-
Container flow:
|
|
9
|
-
Pre-fit: SimulationSpec + VaryingSpec -> DataBundle (synthetic data)
|
|
10
|
-
Post-fit: FitState -> simulated response arrays
|
|
11
|
-
Power: sweep parameters -> Polars DataFrame (power results)
|
|
12
|
-
|
|
13
|
-
Submodules:
|
|
14
|
-
dgp/: Data generating process functions (lm, glm, lmer, glmer)
|
|
15
|
-
model_sim: Response simulation from fitted model parameters
|
|
16
|
-
harness: Monte Carlo iteration runner and MonteCarloResult container
|
|
17
|
-
metrics: Recovery metrics (bias, RMSE, coverage, rejection rate)
|
|
18
|
-
power: Power analysis and parameter sweep utilities
|
|
19
7
|
"""
|
|
20
8
|
|
|
21
9
|
from bossanova.internal.simulation.dgp import (
|
|
@@ -63,7 +63,7 @@ def plot_explore(
|
|
|
63
63
|
hue: str | None = None,
|
|
64
64
|
col: str | None = None,
|
|
65
65
|
row: str | None = None,
|
|
66
|
-
|
|
66
|
+
effect_scale: Literal["link", "response"] = "response",
|
|
67
67
|
conf_int: float = 0.95,
|
|
68
68
|
prettify: bool = False,
|
|
69
69
|
height: float = 4.0,
|
|
@@ -98,9 +98,8 @@ def plot_explore(
|
|
|
98
98
|
Auto-detected from conditioning columns when None.
|
|
99
99
|
col: Column faceting variable.
|
|
100
100
|
row: Row faceting variable.
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
- ``"link"``: Link scale (GLM/GLMER).
|
|
101
|
+
effect_scale: ``"link"`` or ``"response"`` (default).
|
|
102
|
+
Matches ``model.explore(effect_scale=...)``.
|
|
104
103
|
conf_int: Confidence level (default 0.95).
|
|
105
104
|
prettify: Convert axis labels to human-readable format.
|
|
106
105
|
height: Height of each facet in inches.
|
|
@@ -167,7 +166,7 @@ def plot_explore(
|
|
|
167
166
|
if not hasattr(model, "explore"):
|
|
168
167
|
raise AttributeError(f"{type(model).__name__} does not have explore method")
|
|
169
168
|
# Compute MEEs via explore().infer()
|
|
170
|
-
model.explore(specs,
|
|
169
|
+
model.explore(specs, effect_scale=effect_scale).infer(conf_level=conf_int)
|
|
171
170
|
effects_df = model.effects
|
|
172
171
|
mee = model._mee
|
|
173
172
|
result_type = mee.type
|
|
@@ -268,6 +268,16 @@ def build_prediction_data(
|
|
|
268
268
|
rows = [dict(zip(keys, combo)) for combo in product(*values)]
|
|
269
269
|
pred_grid = pl.DataFrame(rows)
|
|
270
270
|
|
|
271
|
+
# Save model state — plot_predict should not have side effects on
|
|
272
|
+
# _last_op or _pred, since users may call .infer() after plotting and
|
|
273
|
+
# expect it to route back to the pre-plot operation (e.g. "fit").
|
|
274
|
+
# Unwrap ModelResult proxy (has __slots__, can't set attrs directly).
|
|
275
|
+
from bossanova.model.result import ModelResult
|
|
276
|
+
|
|
277
|
+
_core = model._model if isinstance(model, ModelResult) else model
|
|
278
|
+
saved_last_op = _core._last_op
|
|
279
|
+
saved_pred = _core._pred
|
|
280
|
+
|
|
271
281
|
# Get predictions — request intervals in first call when possible to
|
|
272
282
|
# avoid a redundant second model.predict() invocation.
|
|
273
283
|
predict_kwargs: dict = {"type": pred_type}
|
|
@@ -352,6 +362,10 @@ def build_prediction_data(
|
|
|
352
362
|
|
|
353
363
|
result_df = pl.concat([result_df, pop_df], how="diagonal")
|
|
354
364
|
|
|
365
|
+
# Restore model state so plot_predict doesn't affect subsequent .infer()
|
|
366
|
+
_core._last_op = saved_last_op
|
|
367
|
+
_core._pred = saved_pred
|
|
368
|
+
|
|
355
369
|
return result_df
|
|
356
370
|
|
|
357
371
|
|