bossanova 0.1.0.dev17__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.
Files changed (259) hide show
  1. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/.gitignore +1 -1
  2. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/PKG-INFO +16 -1
  3. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/README.md +15 -0
  4. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/__init__.py +5 -1
  5. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/data/__init__.py +18 -2
  6. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/expressions.py +13 -13
  7. bossanova-0.1.0.dev19/bossanova/internal/compare/__init__.py +12 -0
  8. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/compare/compare.py +28 -11
  9. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/compare/cv.py +5 -5
  10. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/compare/deviance.py +1 -1
  11. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/compare/f_test.py +1 -1
  12. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/compare/helpers.py +3 -3
  13. bossanova-0.1.0.dev19/bossanova/internal/compare/ic.py +160 -0
  14. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/compare/lrt.py +1 -1
  15. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/compare/lrt_compare.py +1 -1
  16. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/compare/refit.py +1 -1
  17. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/containers/builders/dataframes.py +2 -1
  18. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/containers/builders/results.py +1 -2
  19. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/containers/builders/specs.py +13 -4
  20. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/containers/schemas.py +3 -2
  21. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/containers/structs/data.py +1 -1
  22. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/containers/structs/display.py +50 -1
  23. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/containers/structs/explore.py +4 -0
  24. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/containers/structs/specs.py +3 -1
  25. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/containers/structs/state.py +52 -19
  26. {bossanova-0.1.0.dev17/bossanova/internal/maths → bossanova-0.1.0.dev19/bossanova/internal}/design/__init__.py +26 -31
  27. {bossanova-0.1.0.dev17/bossanova/internal/maths → bossanova-0.1.0.dev19/bossanova/internal}/design/coding.py +44 -250
  28. {bossanova-0.1.0.dev17/bossanova/internal/maths → bossanova-0.1.0.dev19/bossanova/internal}/design/reference.py +1 -1
  29. bossanova-0.1.0.dev19/bossanova/internal/fit/__init__.py +57 -0
  30. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal/fit}/convergence.py +1 -1
  31. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal/fit}/diagnostics.py +29 -5
  32. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/fit/dispatch.py +88 -23
  33. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/fit/glm.py +5 -13
  34. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/fit/glmer.py +13 -20
  35. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/fit/lmer.py +7 -17
  36. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/fit/ols.py +0 -7
  37. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal/fit}/predict.py +6 -6
  38. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/formula/__init__.py +11 -6
  39. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal/formula}/bundle.py +28 -4
  40. {bossanova-0.1.0.dev17/bossanova/internal/operations/common → bossanova-0.1.0.dev19/bossanova/internal/formula}/contrast_registry.py +11 -1
  41. bossanova-0.1.0.dev17/bossanova/internal/operations/contrasts.py → bossanova-0.1.0.dev19/bossanova/internal/formula/contrast_specs.py +13 -13
  42. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/formula/design.py +2 -2
  43. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/formula/encoding.py +45 -25
  44. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/formula/evaluate.py +46 -73
  45. bossanova-0.1.0.dev19/bossanova/internal/formula/evaluate_contrast.py +399 -0
  46. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/formula/evaluate_newdata.py +7 -39
  47. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/formula/evaluate_transforms.py +6 -79
  48. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/formula/helpers.py +1 -34
  49. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/formula/parse.py +4 -4
  50. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/formula/parser/__init__.py +12 -1
  51. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/formula/parser/expr.py +19 -0
  52. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/formula/parser/parser.py +26 -1
  53. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/formula/random_effects.py +143 -135
  54. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/infer/__init__.py +21 -15
  55. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/infer/asymptotic.py +34 -9
  56. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/infer/bootstrap.py +22 -18
  57. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/infer/cv.py +17 -19
  58. bossanova-0.1.0.dev19/bossanova/internal/infer/dispatch.py +491 -0
  59. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/infer/mee.py +22 -14
  60. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/infer/params.py +31 -43
  61. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/infer/permutation.py +3 -3
  62. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/infer/prediction.py +14 -9
  63. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/infer/profile.py +14 -8
  64. bossanova-0.1.0.dev19/bossanova/internal/infer/resample/__init__.py +49 -0
  65. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal/infer}/resample/common.py +1 -1
  66. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal/infer}/resample/glmer.py +50 -66
  67. bossanova-0.1.0.dev19/bossanova/internal/infer/resample/lm_operators.py +151 -0
  68. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal/infer}/resample/lmer.py +15 -24
  69. bossanova-0.1.0.dev19/bossanova/internal/infer/resample/results.py +136 -0
  70. bossanova-0.1.0.dev19/bossanova/internal/infer/resample/simulate.py +124 -0
  71. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/infer/satterthwaite_emm.py +3 -3
  72. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/marginal/__init__.py +34 -29
  73. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/marginal/bracket_contrasts.py +3 -3
  74. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/marginal/compute.py +61 -63
  75. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/marginal/contrasts.py +105 -261
  76. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/marginal/emm.py +4 -4
  77. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/marginal/explore.py +2 -2
  78. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/marginal/explore_parser.py +25 -2
  79. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/marginal/explore_scanner.py +2 -2
  80. {bossanova-0.1.0.dev17/bossanova/internal/operations/common → bossanova-0.1.0.dev19/bossanova/internal/marginal}/factors.py +4 -4
  81. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/marginal/grid.py +3 -3
  82. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/marginal/inference.py +2 -2
  83. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/marginal/joint_tests.py +3 -3
  84. bossanova-0.1.0.dev17/bossanova/internal/maths/inference/contrasts.py → bossanova-0.1.0.dev19/bossanova/internal/marginal/matrices.py +114 -111
  85. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/marginal/slopes.py +8 -6
  86. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal/marginal}/transforms.py +8 -8
  87. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/__init__.py +22 -42
  88. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/distributions/__init__.py +1 -1
  89. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/inference/__init__.py +0 -18
  90. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/inference/welch.py +12 -9
  91. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/linalg/__init__.py +2 -4
  92. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/linalg/schur.py +3 -3
  93. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/linalg/sparse.py +3 -70
  94. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/solvers/glmer.py +1 -7
  95. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/solvers/lambda_template.py +3 -3
  96. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/solvers/lmer.py +2 -2
  97. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/solvers/pirls_sparse.py +3 -3
  98. bossanova-0.1.0.dev19/bossanova/internal/rendering/__init__.py +22 -0
  99. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/rendering/latex.py +7 -7
  100. bossanova-0.1.0.dev19/bossanova/internal/rendering/markdown.py +163 -0
  101. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/simulation/__init__.py +17 -20
  102. bossanova-0.1.0.dev19/bossanova/internal/simulation/dgp/__init__.py +13 -0
  103. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/simulation/dgp/glm.py +2 -2
  104. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/simulation/dgp/glmer.py +2 -2
  105. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/simulation/dgp/lm.py +2 -2
  106. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/simulation/dgp/lmer.py +2 -2
  107. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/simulation/harness.py +11 -11
  108. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/simulation/metrics.py +3 -23
  109. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/simulation/power.py +149 -8
  110. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/viz/README.md +2 -2
  111. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/viz/__init__.py +25 -3
  112. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/viz/core.py +2 -0
  113. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/viz/core_viz.py +66 -3
  114. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/viz/design.py +50 -71
  115. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/viz/fit_layers.py +19 -36
  116. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/viz/helpers.py +85 -1
  117. bossanova-0.1.0.dev19/bossanova/internal/viz/mem.py +642 -0
  118. bossanova-0.1.0.dev19/bossanova/internal/viz/mem_forest.py +538 -0
  119. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/viz/params.py +31 -0
  120. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/viz/predict.py +48 -45
  121. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/viz/profile.py +50 -12
  122. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/viz/resamples.py +13 -13
  123. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/viz/resid.py +3 -0
  124. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/viz/vif.py +6 -13
  125. bossanova-0.1.0.dev19/bossanova/model/__init__.py +7 -0
  126. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/model/core.py +447 -398
  127. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/model/result.py +84 -0
  128. bossanova-0.1.0.dev19/bossanova/model/summary.py +1103 -0
  129. bossanova-0.1.0.dev19/pyproject.toml +246 -0
  130. bossanova-0.1.0.dev17/bossanova/internal/containers/builders/data.py +0 -10
  131. bossanova-0.1.0.dev17/bossanova/internal/operations/__init__.py +0 -195
  132. bossanova-0.1.0.dev17/bossanova/internal/operations/common/__init__.py +0 -33
  133. bossanova-0.1.0.dev17/bossanova/internal/operations/common/data_utils.py +0 -36
  134. bossanova-0.1.0.dev17/bossanova/internal/operations/compare/__init__.py +0 -6
  135. bossanova-0.1.0.dev17/bossanova/internal/operations/fit/__init__.py +0 -31
  136. bossanova-0.1.0.dev17/bossanova/internal/operations/profile.py +0 -8
  137. bossanova-0.1.0.dev17/bossanova/internal/operations/rendering/__init__.py +0 -5
  138. bossanova-0.1.0.dev17/bossanova/internal/operations/resample/__init__.py +0 -75
  139. bossanova-0.1.0.dev17/bossanova/internal/operations/resample/glm.py +0 -786
  140. bossanova-0.1.0.dev17/bossanova/internal/operations/resample/lm.py +0 -796
  141. bossanova-0.1.0.dev17/bossanova/internal/operations/resample/lm_bca.py +0 -326
  142. bossanova-0.1.0.dev17/bossanova/internal/operations/resample/lm_operators.py +0 -337
  143. bossanova-0.1.0.dev17/bossanova/internal/operations/resample/mixed.py +0 -14
  144. bossanova-0.1.0.dev17/bossanova/internal/operations/resample/results.py +0 -299
  145. bossanova-0.1.0.dev17/bossanova/internal/operations/resample/utils.py +0 -128
  146. bossanova-0.1.0.dev17/bossanova/internal/operations/simulation/dgp/__init__.py +0 -13
  147. bossanova-0.1.0.dev17/bossanova/internal/viz/mem.py +0 -478
  148. bossanova-0.1.0.dev17/bossanova/model/__init__.py +0 -6
  149. bossanova-0.1.0.dev17/bossanova/model/summary.py +0 -467
  150. bossanova-0.1.0.dev17/pyproject.toml +0 -580
  151. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/LICENSE +0 -0
  152. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/data/README.md +0 -0
  153. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/data/advertising.csv +0 -0
  154. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/data/cake.csv +0 -0
  155. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/data/chickweight.csv +0 -0
  156. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/data/credit.csv +0 -0
  157. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/data/gammas.csv +0 -0
  158. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/data/mtcars.csv +0 -0
  159. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/data/penguins.csv +0 -0
  160. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/data/poker.csv +0 -0
  161. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/data/sleep.csv +0 -0
  162. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/data/titanic.csv +0 -0
  163. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/data/titanic_test.csv +0 -0
  164. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/data/titanic_train.csv +0 -0
  165. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/distributions/__init__.py +0 -0
  166. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/distributions/continuous.py +0 -0
  167. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/distributions/discrete.py +0 -0
  168. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/distributions/varying.py +0 -0
  169. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/__init__.py +0 -0
  170. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/containers/__init__.py +0 -0
  171. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/containers/builders/__init__.py +0 -0
  172. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/containers/builders/resamples.py +0 -0
  173. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/containers/builders/state.py +0 -0
  174. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/containers/structs/__init__.py +0 -0
  175. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/containers/structs/formula.py +0 -0
  176. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/containers/validators.py +0 -0
  177. {bossanova-0.1.0.dev17/bossanova/internal/maths → bossanova-0.1.0.dev19/bossanova/internal}/design/names.py +0 -0
  178. {bossanova-0.1.0.dev17/bossanova/internal/maths → bossanova-0.1.0.dev19/bossanova/internal}/design/z_matrix.py +0 -0
  179. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/fit/rank.py +0 -0
  180. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal/fit}/varying.py +0 -0
  181. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/formula/parser/scanner.py +0 -0
  182. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/formula/parser/token.py +0 -0
  183. {bossanova-0.1.0.dev17/bossanova/internal/operations/common → bossanova-0.1.0.dev19/bossanova/internal/infer}/formula_utils.py +0 -0
  184. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal/infer}/resample/core.py +0 -0
  185. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/infer/resample_bundle.py +0 -0
  186. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/infer/simulation.py +0 -0
  187. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/marginal/conditions.py +0 -0
  188. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/marginal/validation.py +0 -0
  189. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/backend/__init__.py +0 -0
  190. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/backend/dispatch.py +0 -0
  191. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/backend/jax.py +0 -0
  192. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/backend/numpy.py +0 -0
  193. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/backend/protocol.py +0 -0
  194. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/batching.py +0 -0
  195. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/config.py +0 -0
  196. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/convergence.py +0 -0
  197. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/differentiation.py +0 -0
  198. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/distributions/algebra.py +0 -0
  199. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/distributions/base.py +0 -0
  200. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/distributions/core.py +0 -0
  201. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/distributions/derived.py +0 -0
  202. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/distributions/factories.py +0 -0
  203. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/distributions/plotting.py +0 -0
  204. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/distributions/probability.py +0 -0
  205. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/family/__init__.py +0 -0
  206. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/family/binomial.py +0 -0
  207. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/family/create.py +0 -0
  208. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/family/gamma.py +0 -0
  209. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/family/gaussian.py +0 -0
  210. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/family/links.py +0 -0
  211. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/family/poisson.py +0 -0
  212. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/family/response.py +0 -0
  213. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/family/schema.py +0 -0
  214. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/family/tdist.py +0 -0
  215. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/inference/diagnostics.py +0 -0
  216. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/inference/estimation.py +0 -0
  217. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/inference/hypothesis.py +0 -0
  218. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/inference/information_criteria.py +0 -0
  219. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/inference/multiplicity.py +0 -0
  220. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/inference/profile.py +0 -0
  221. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/inference/sandwich.py +0 -0
  222. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/inference/satterthwaite.py +0 -0
  223. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/inference/wald_variance.py +0 -0
  224. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/linalg/qr.py +0 -0
  225. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/linalg/svd.py +0 -0
  226. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/predict.py +0 -0
  227. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/rng.py +0 -0
  228. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/rounding.py +0 -0
  229. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/solvers/__init__.py +0 -0
  230. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/solvers/glm.py +0 -0
  231. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/solvers/heuristics.py +0 -0
  232. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/solvers/initialization.py +0 -0
  233. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/solvers/lambda_builder.py +0 -0
  234. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/solvers/lambda_sparse.py +0 -0
  235. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/solvers/optimize.py +0 -0
  236. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/solvers/quadrature.py +0 -0
  237. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/tolerances.py +0 -0
  238. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/transforms.py +0 -0
  239. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/variance.py +0 -0
  240. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/maths/weights.py +0 -0
  241. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/simulation/dgp/generate.py +0 -0
  242. {bossanova-0.1.0.dev17/bossanova/internal/operations → bossanova-0.1.0.dev19/bossanova/internal}/simulation/model_sim.py +0 -0
  243. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/viz/cognition.py +0 -0
  244. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/viz/compare.py +0 -0
  245. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/viz/core_data.py +0 -0
  246. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/viz/core_protocols.py +0 -0
  247. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/viz/core_sizing.py +0 -0
  248. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/viz/dag.py +0 -0
  249. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/viz/fit.py +0 -0
  250. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/viz/fit_builders.py +0 -0
  251. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/viz/lattice.py +0 -0
  252. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/viz/layout.py +0 -0
  253. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/viz/ranef.py +0 -0
  254. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/internal/viz/relationships.py +0 -0
  255. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/model/guards.py +0 -0
  256. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/bossanova/py.typed +0 -0
  257. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/tests/bossanova_benchmarks/bootstrap/data/README.md +0 -0
  258. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/tests/bossanova_benchmarks/insteval/data/README.md +0 -0
  259. {bossanova-0.1.0.dev17 → bossanova-0.1.0.dev19}/tests/bossanova_tests/hypothesis/README.md +0 -0
@@ -78,7 +78,7 @@ COMPARISON-REPORT.md
78
78
  ERROR_MESSAGE_IMPROVEMENTS.md
79
79
  *.qmd
80
80
  bossanova-docs/apidocs/
81
- bossanova-docs/help/
81
+ bossanova-docs/api/
82
82
  bossanova-docs/wip/
83
83
  .hypothesis/
84
84
  research.md
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bossanova
3
- Version: 0.1.0.dev17
3
+ Version: 0.1.0.dev19
4
4
  Summary: Bridging statistical cultures with some jazz
5
5
  Author: Eshin Jolly
6
6
  License-Expression: MIT
@@ -70,4 +70,19 @@ m.explore("Days")
70
70
  m.effects
71
71
  ```
72
72
 
73
+ ## Development
74
+
75
+ ```bash
76
+ # Install dependencies
77
+ pixi install
78
+
79
+ # Install the IPython kernel (required for notebooks)
80
+ pixi run setup-kernel
81
+
82
+ # Run the full lint + type-check chain
83
+ pixi run lint
84
+
85
+ # Run fast unit tests
86
+ pixi run test
87
+ ```
73
88
 
@@ -42,4 +42,19 @@ m.explore("Days")
42
42
  m.effects
43
43
  ```
44
44
 
45
+ ## Development
46
+
47
+ ```bash
48
+ # Install dependencies
49
+ pixi install
50
+
51
+ # Install the IPython kernel (required for notebooks)
52
+ pixi run setup-kernel
53
+
54
+ # Run the full lint + type-check chain
55
+ pixi run lint
56
+
57
+ # Run fast unit tests
58
+ pixi run test
59
+ ```
45
60
 
@@ -31,11 +31,14 @@ from bossanova.data import ( # noqa: E402
31
31
  from bossanova.model import model # noqa: E402
32
32
 
33
33
  # Statistics
34
- from bossanova.internal.operations.compare import compare, lrt # noqa: E402
34
+ from bossanova.internal.compare import compare, lrt # noqa: E402
35
35
 
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: (11, 2)
71
+ # shape: (12, 2)
56
72
  # ┌───────────────┬─────────────────────────────────┐
57
73
  # │ name ┆ description │
58
74
  # │ --- ┆ --- │
@@ -2,19 +2,19 @@
2
2
 
3
3
  This module provides stateless Polars expressions for data transformations
4
4
  commonly used in statistical modeling. These match the semantics of the
5
- formula-based transforms in `bossanova.internal.operations.formula`.
6
-
7
- Core Transforms:
8
- center(col): x - mean(x) — subtract mean only
9
- norm(col): x / std(x) — divide by std only (normalize magnitude)
10
- zscore(col): (x - mean(x)) / std(x) — traditional z-score (1 SD)
11
- scale(col): (x - mean(x)) / (2 * std(x)) — Gelman scaling (2 SD)
12
-
13
- Additional Helpers:
14
- rank(col, method): Average-method rank transform (matches R's rank())
15
- winsorize(col, lower, upper): Percentile capping for outliers
16
- lag(col, n): Lagged (shifted backward) values
17
- lead(col, n): Lead (shifted forward) values
5
+ formula-based transforms in `bossanova.internal.formula`.
6
+
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"]
@@ -35,16 +35,17 @@ import polars as pl
35
35
 
36
36
  from bossanova.internal.maths.config import get_display_digits
37
37
  from bossanova.internal.maths.rounding import round_float_columns
38
- from bossanova.internal.operations.compare.cv import compare_cv
39
- from bossanova.internal.operations.compare.deviance import compare_deviance
40
- from bossanova.internal.operations.compare.f_test import compare_f_test
41
- from bossanova.internal.operations.compare.helpers import (
42
- infer_method,
38
+ from bossanova.internal.compare.cv import compare_cv
39
+ from bossanova.internal.compare.deviance import compare_deviance
40
+ from bossanova.internal.compare.f_test import compare_f_test
41
+ from bossanova.internal.compare.helpers import (
42
+ resolve_method,
43
43
  sort_models_by_complexity,
44
44
  validate_models,
45
45
  )
46
- from bossanova.internal.operations.compare.lrt_compare import compare_lrt
47
- from bossanova.internal.operations.compare.refit import refit_with_ml
46
+ from bossanova.internal.compare.ic import compare_aic, compare_bic
47
+ from bossanova.internal.compare.lrt_compare import compare_lrt
48
+ from bossanova.internal.compare.refit import refit_with_ml
48
49
 
49
50
  __all__ = ["compare"]
50
51
 
@@ -78,6 +79,8 @@ def compare(
78
79
  - "lrt": Likelihood ratio test (for mixed models)
79
80
  - "deviance": Deviance test (for glm)
80
81
  - "cv": Cross-validation comparison (for lm/glm)
82
+ - "aic": AIC comparison with delta-AIC and Akaike weights
83
+ - "bic": BIC comparison with delta-BIC and Schwarz weights
81
84
  sort: If True, sort models by complexity before comparing.
82
85
  This ensures proper nesting order.
83
86
  refit: If True and models are lmer/glmer with REML estimation,
@@ -140,6 +143,15 @@ def compare(
140
143
  - diff_se: Nadeau-Bengio corrected standard error
141
144
  - p_value: Two-sided p-value
142
145
 
146
+ For AIC/BIC comparison:
147
+ - model: Formula string
148
+ - npar: Number of estimated parameters
149
+ - loglik: Log-likelihood
150
+ - deviance: Deviance (-2 * loglik)
151
+ - AIC/BIC: Information criteria
152
+ - delta_AIC/delta_BIC: Difference from best model
153
+ - weight: Akaike/Schwarz weight (model probability)
154
+
143
155
  Raises:
144
156
  ValueError: If models are not valid for comparison.
145
157
 
@@ -211,15 +223,15 @@ def compare(
211
223
  # Validate and auto-fit models (pass method and refit for REML check)
212
224
  models = validate_models(models, method=method, refit=refit)
213
225
 
214
- # Sort if requested (not applicable for CV)
215
- if sort and method != "cv":
226
+ # Sort if requested (not applicable for CV or IC methods which sort internally)
227
+ if sort and method not in ("cv", "aic", "bic"):
216
228
  model_list = sort_models_by_complexity(models)
217
229
  else:
218
230
  model_list = list(models)
219
231
 
220
232
  # Infer method if auto
221
233
  if method == "auto":
222
- method = infer_method(model_list[0])
234
+ method = resolve_method(model_list[0])
223
235
 
224
236
  # For LRT with refit=True, refit REML models with ML
225
237
  if method == "lrt" and refit:
@@ -234,9 +246,14 @@ def compare(
234
246
  result = compare_deviance(model_list, test=test)
235
247
  elif method == "cv":
236
248
  result = compare_cv(model_list, cv=cv, seed=seed, metric=metric)
249
+ elif method == "aic":
250
+ result = compare_aic(model_list)
251
+ elif method == "bic":
252
+ result = compare_bic(model_list)
237
253
  else:
238
254
  raise ValueError(
239
- f"Unknown method: {method}. Use 'auto', 'f', 'lrt', 'deviance', or 'cv'."
255
+ f"Unknown method: {method}. "
256
+ "Use 'auto', 'f', 'lrt', 'deviance', 'cv', 'aic', or 'bic'."
240
257
  )
241
258
 
242
259
  # Round float columns to significant figures (digits=0 disables rounding)
@@ -13,19 +13,19 @@ from scipy import stats
13
13
 
14
14
  from bossanova.internal.containers.schemas import Col, ComparisonCv
15
15
  from bossanova.internal.maths.rng import RNG
16
- from bossanova.internal.operations.compare.helpers import get_model_type
17
- from bossanova.internal.operations.resample.core import (
16
+ from bossanova.internal.compare.helpers import get_model_type
17
+ from bossanova.internal.infer.resample.core import (
18
18
  generate_kfold_indices,
19
19
  generate_loo_indices,
20
20
  )
21
21
 
22
22
  __all__ = [
23
23
  "compare_cv",
24
- "cv_fold_score",
24
+ "compute_cv_fold_score",
25
25
  ]
26
26
 
27
27
 
28
- def cv_fold_score(
28
+ def compute_cv_fold_score(
29
29
  model: Any,
30
30
  train_idx: np.ndarray,
31
31
  test_idx: np.ndarray,
@@ -142,7 +142,7 @@ def compare_cv(
142
142
 
143
143
  for train_idx, test_idx in splits:
144
144
  for i, model in enumerate(models):
145
- score = cv_fold_score(model, train_idx, test_idx, metric)
145
+ score = compute_cv_fold_score(model, train_idx, test_idx, metric)
146
146
  fold_scores[i].append(score)
147
147
 
148
148
  # Convert to arrays
@@ -14,7 +14,7 @@ from bossanova.internal.containers.schemas import (
14
14
  ComparisonDevianceChi2,
15
15
  ComparisonDevianceF,
16
16
  )
17
- from bossanova.internal.operations.compare.helpers import check_nested
17
+ from bossanova.internal.compare.helpers import check_nested
18
18
 
19
19
  __all__ = [
20
20
  "compare_deviance",
@@ -10,7 +10,7 @@ import polars as pl
10
10
  from scipy import stats
11
11
 
12
12
  from bossanova.internal.containers.schemas import Col, ComparisonFTest
13
- from bossanova.internal.operations.compare.helpers import check_nested
13
+ from bossanova.internal.compare.helpers import check_nested
14
14
 
15
15
  __all__ = [
16
16
  "compare_f_test",
@@ -15,7 +15,7 @@ if TYPE_CHECKING:
15
15
  __all__ = [
16
16
  "check_nested",
17
17
  "get_model_type",
18
- "infer_method",
18
+ "resolve_method",
19
19
  "sort_models_by_complexity",
20
20
  "validate_models",
21
21
  ]
@@ -100,7 +100,7 @@ def validate_models(
100
100
 
101
101
  # For LRT, check that all models use ML estimation (unless refit=True)
102
102
  model_type = model_types[0]
103
- inferred_method = method if method != "auto" else infer_method(models[0])
103
+ inferred_method = method if method != "auto" else resolve_method(models[0])
104
104
 
105
105
  if inferred_method == "lrt" and model_type in ("lmer", "glmer") and not refit:
106
106
  methods = [m._spec.method for m in models]
@@ -151,7 +151,7 @@ def sort_models_by_complexity(models: tuple[Any, ...]) -> list[Any]:
151
151
  return sorted(models, key=get_total_params)
152
152
 
153
153
 
154
- def infer_method(model: Any) -> str:
154
+ def resolve_method(model: Any) -> str:
155
155
  """Infer the appropriate comparison method for a model type.
156
156
 
157
157
  Uses :func:`classify_model_type` to canonically determine the model type
@@ -0,0 +1,160 @@
1
+ """Information criterion comparison for model selection.
2
+
3
+ Computes AIC/BIC tables with delta-IC and Akaike/Schwarz weights,
4
+ following Burnham & Anderson (2002). Unlike hypothesis-test comparisons
5
+ (F-test, LRT, deviance), IC comparison does not require model nesting —
6
+ any set of models fitted to the same data can be compared.
7
+
8
+ Functions:
9
+ compare_aic: Rank models by AIC with delta-AIC and Akaike weights.
10
+ compare_bic: Rank models by BIC with delta-BIC and Schwarz weights.
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import math
16
+ from typing import Any
17
+
18
+ import polars as pl
19
+
20
+ from bossanova.internal.containers.schemas import (
21
+ Col,
22
+ ComparisonAic,
23
+ ComparisonBic,
24
+ )
25
+ from bossanova.internal.maths.family import ESTIMATED_DISPERSION_FAMILIES
26
+ from bossanova.internal.maths.inference import compute_aic, compute_bic
27
+
28
+ __all__ = ["compare_aic", "compare_bic"]
29
+
30
+
31
+ def _get_n_params_ic(model: Any) -> int:
32
+ """Get total number of estimated parameters for IC computation.
33
+
34
+ Follows the same counting as ``compute_diagnostics()``:
35
+
36
+ - ``rank`` (estimable fixed effects)
37
+ - ``+ len(theta)`` for mixed models (variance parameters)
38
+ - ``+ 1`` for families with estimated dispersion (e.g. Gaussian sigma)
39
+
40
+ Args:
41
+ model: A fitted model instance.
42
+
43
+ Returns:
44
+ Total parameter count for AIC/BIC computation.
45
+ """
46
+ k: int = model._bundle.rank
47
+ if model._fit.theta is not None:
48
+ k += len(model._fit.theta)
49
+ if model._spec.family in ESTIMATED_DISPERSION_FAMILIES:
50
+ k += 1
51
+ return k
52
+
53
+
54
+ def compare_aic(models: list[Any]) -> pl.DataFrame:
55
+ """Compare models by AIC with delta-AIC and Akaike weights.
56
+
57
+ Models are sorted by AIC (best first). Delta-AIC is the difference
58
+ from the best model. Akaike weights represent the relative likelihood
59
+ of each model being the best, following Burnham & Anderson (2002):
60
+
61
+ w_i = exp(-0.5 * delta_i) / sum(exp(-0.5 * delta_j))
62
+
63
+ Args:
64
+ models: List of fitted model objects (at least 2).
65
+
66
+ Returns:
67
+ DataFrame with columns: model, npar, loglik, deviance, AIC, BIC,
68
+ delta_AIC, weight. Sorted by AIC ascending (best model first).
69
+ """
70
+ return _compare_ic(models, criterion="aic")
71
+
72
+
73
+ def compare_bic(models: list[Any]) -> pl.DataFrame:
74
+ """Compare models by BIC with delta-BIC and Schwarz weights.
75
+
76
+ Models are sorted by BIC (best first). Delta-BIC is the difference
77
+ from the best model. Schwarz weights use the same formula as Akaike
78
+ weights but applied to BIC differences.
79
+
80
+ Args:
81
+ models: List of fitted model objects (at least 2).
82
+
83
+ Returns:
84
+ DataFrame with columns: model, npar, loglik, deviance, AIC, BIC,
85
+ delta_BIC, weight. Sorted by BIC ascending (best model first).
86
+ """
87
+ return _compare_ic(models, criterion="bic")
88
+
89
+
90
+ def _compare_ic(models: list[Any], *, criterion: str) -> pl.DataFrame:
91
+ """Shared implementation for AIC/BIC comparison.
92
+
93
+ Args:
94
+ models: List of fitted models.
95
+ criterion: ``"aic"`` or ``"bic"``.
96
+
97
+ Returns:
98
+ DataFrame sorted by the chosen criterion with delta-IC and weights.
99
+ """
100
+ formulas: list[str] = []
101
+ npars: list[int] = []
102
+ logliks: list[float] = []
103
+ deviances: list[float] = []
104
+ aics: list[float] = []
105
+ bics: list[float] = []
106
+
107
+ for m in models:
108
+ k = _get_n_params_ic(m)
109
+ loglik = float(m._fit.loglik)
110
+ n = m._bundle.n
111
+
112
+ formulas.append(m.formula)
113
+ npars.append(k)
114
+ logliks.append(loglik)
115
+ deviances.append(-2.0 * loglik)
116
+ aics.append(compute_aic(loglik, k))
117
+ bics.append(compute_bic(loglik, k, n))
118
+
119
+ # Select criterion and schema
120
+ if criterion == "aic":
121
+ ic_values = aics
122
+ delta_col = Col.DELTA_AIC
123
+ schema = ComparisonAic
124
+ else:
125
+ ic_values = bics
126
+ delta_col = Col.DELTA_BIC
127
+ schema = ComparisonBic
128
+
129
+ # Sort all lists by IC value (ascending = best first)
130
+ order = sorted(range(len(models)), key=lambda i: ic_values[i])
131
+ formulas = [formulas[i] for i in order]
132
+ npars = [npars[i] for i in order]
133
+ logliks = [logliks[i] for i in order]
134
+ deviances = [deviances[i] for i in order]
135
+ aics = [aics[i] for i in order]
136
+ bics = [bics[i] for i in order]
137
+ ic_values = [ic_values[i] for i in order]
138
+
139
+ # Delta-IC: difference from best model
140
+ ic_min = ic_values[0]
141
+ deltas = [v - ic_min for v in ic_values]
142
+
143
+ # Akaike/Schwarz weights: exp(-0.5 * delta) / sum(exp(-0.5 * delta))
144
+ raw_weights = [math.exp(-0.5 * d) for d in deltas]
145
+ weight_sum = sum(raw_weights)
146
+ weights = [w / weight_sum for w in raw_weights]
147
+
148
+ return pl.DataFrame(
149
+ {
150
+ Col.MODEL: formulas,
151
+ Col.NPAR: npars,
152
+ Col.LOGLIK: logliks,
153
+ Col.DEVIANCE: deviances,
154
+ Col.AIC_R: aics,
155
+ Col.BIC_R: bics,
156
+ delta_col: deltas,
157
+ Col.WEIGHT: weights,
158
+ },
159
+ schema=schema,
160
+ )
@@ -4,7 +4,7 @@ from typing import Any
4
4
 
5
5
  import polars as pl
6
6
 
7
- from bossanova.internal.operations.compare.compare import compare
7
+ from bossanova.internal.compare.compare import compare
8
8
 
9
9
  __all__ = ["lrt"]
10
10
 
@@ -16,7 +16,7 @@ from bossanova.internal.containers.schemas import (
16
16
  from bossanova.internal.maths.config import is_singular
17
17
  from bossanova.internal.maths.inference import compute_aic as compute_aic
18
18
  from bossanova.internal.maths.inference import compute_bic as _compute_bic
19
- from bossanova.internal.operations.compare.helpers import check_nested, get_model_type
19
+ from bossanova.internal.compare.helpers import check_nested, get_model_type
20
20
 
21
21
  __all__ = [
22
22
  "compare_lrt",
@@ -6,7 +6,7 @@ estimation when the original uses REML, enabling valid likelihood ratio tests.
6
6
 
7
7
  from typing import Any
8
8
 
9
- from bossanova.internal.operations.compare.helpers import get_model_type
9
+ from bossanova.internal.compare.helpers import get_model_type
10
10
 
11
11
  __all__ = [
12
12
  "refit_with_ml",
@@ -61,7 +61,7 @@ def build_params_dataframe(
61
61
  Column set varies by inference method:
62
62
 
63
63
  - **asymp**: all inference columns (p_value last).
64
- - **boot**: no p_value; df = n_resamples.
64
+ - **boot**: all inference columns; df = n_resamples.
65
65
  - **perm**: no CIs; df = n_valid_resamples.
66
66
  - **cv**: PRE columns only.
67
67
  - **None**: term + estimate only.
@@ -96,6 +96,7 @@ def build_params_dataframe(
96
96
  data[Col.CI_UPPER] = params_inference.ci_upper.tolist()
97
97
  data[Col.STATISTIC] = params_inference.statistic.tolist()
98
98
  data[Col.DF] = params_inference.df.tolist()
99
+ data[Col.P_VALUE] = params_inference.p_value.tolist()
99
100
  return pl.DataFrame(data, schema=ParamsBoot)
100
101
 
101
102
  if method == "perm":
@@ -28,7 +28,7 @@ _INFERENCE_COLS: tuple[str, ...] = (
28
28
  )
29
29
 
30
30
  # Columns excluded per inference method.
31
- _BOOT_EXCLUDE: frozenset[str] = frozenset({Col.P_VALUE})
31
+ _BOOT_EXCLUDE: frozenset[str] = frozenset()
32
32
  _PERM_EXCLUDE: frozenset[str] = frozenset({Col.CI_LOWER, Col.CI_UPPER})
33
33
 
34
34
 
@@ -43,7 +43,6 @@ def append_inference_columns(
43
43
  column that is not None on *state*. Columns are added in canonical
44
44
  order: se, ci_lower, ci_upper, statistic, df, p_value.
45
45
 
46
- When *method* is ``"boot"``, the ``p_value`` column is excluded.
47
46
  When *method* is ``"perm"``, the ``ci_lower`` and ``ci_upper``
48
47
  columns are excluded.
49
48
 
@@ -173,7 +173,7 @@ def build_model_spec_from_formula(
173
173
  if "~" not in formula:
174
174
  raise ValueError(f"Invalid formula: {formula!r}. Formula must contain '~'.")
175
175
 
176
- from bossanova.internal.operations.formula.parse import extract_formula_structure
176
+ from bossanova.internal.formula.parse import extract_formula_structure
177
177
 
178
178
  try:
179
179
  structure = extract_formula_structure(formula)
@@ -269,13 +269,20 @@ def build_simulation_spec(
269
269
  # =============================================================================
270
270
 
271
271
 
272
+ _CONTRAST_FUNC_RE = (
273
+ r"(?:treatment|dummy|sum|deviation|helmert|sequential|poly)\((\w+)(?:,\s*[^)]+)?\)"
274
+ )
275
+
276
+
272
277
  def parse_formula_simple(formula: str) -> dict[str, Any]:
273
278
  """Simple formula parser for simulation defaults.
274
279
 
275
280
  Parses a model formula to extract variable types for default distributions.
281
+ Recognizes contrast encoding functions (``treatment(x)``, ``sum(x)``, etc.)
282
+ as categorical markers.
276
283
 
277
284
  Args:
278
- formula: Model formula (e.g., "y ~ x + factor(group) + (1|subject)").
285
+ formula: Model formula (e.g., ``"y ~ x + treatment(group) + (1|subject)"``).
279
286
 
280
287
  Returns:
281
288
  Dictionary with keys: response, continuous, factors, re_groups.
@@ -283,6 +290,8 @@ def parse_formula_simple(formula: str) -> dict[str, Any]:
283
290
  Examples:
284
291
  >>> parse_formula_simple("y ~ x + z")
285
292
  {'response': 'y', 'continuous': ['x', 'z'], 'factors': [], 're_groups': []}
293
+ >>> parse_formula_simple("y ~ treatment(group) + x")
294
+ {'response': 'y', 'continuous': ['x'], 'factors': ['group'], 're_groups': []}
286
295
  """
287
296
  if "~" not in formula:
288
297
  msg = f"Invalid formula: missing '~'. Got: {formula}"
@@ -297,10 +306,10 @@ def parse_formula_simple(formula: str) -> dict[str, Any]:
297
306
  msg = f"Invalid formula: empty response variable. Got: {formula}"
298
307
  raise ValueError(msg)
299
308
 
300
- factors = re.findall(r"factor\((\w+)\)", rhs)
309
+ factors = re.findall(_CONTRAST_FUNC_RE, rhs)
301
310
  re_groups = re.findall(r"\([^)]+\|(\w+)\)", rhs)
302
311
 
303
- cleaned = re.sub(r"factor\(\w+\)", "", rhs)
312
+ cleaned = re.sub(_CONTRAST_FUNC_RE, "", rhs)
304
313
  cleaned = re.sub(r"\([^)]+\|\w+\)", "", cleaned)
305
314
 
306
315
  all_terms = re.findall(r"\b([a-zA-Z_]\w*)\b", cleaned)
@@ -231,6 +231,7 @@ ParamsBoot = Schema(
231
231
  Col.CI_UPPER: Float64,
232
232
  Col.STATISTIC: Float64,
233
233
  Col.DF: Float64,
234
+ Col.P_VALUE: Float64,
234
235
  }
235
236
  )
236
237
 
@@ -528,7 +529,7 @@ VaryingCorrSchema = Schema(
528
529
  # compare() Schemas (rows = models)
529
530
  # =============================================================================
530
531
 
531
- # Currently unused retained as reference schema for AIC-based comparison.
532
+ # AIC-based model comparison (used by compare(method='aic')).
532
533
  ComparisonAic = Schema(
533
534
  {
534
535
  Col.MODEL: String,
@@ -542,7 +543,7 @@ ComparisonAic = Schema(
542
543
  }
543
544
  )
544
545
 
545
- # Currently unused retained as reference schema for BIC-based comparison.
546
+ # BIC-based model comparison (used by compare(method='bic')).
546
547
  ComparisonBic = Schema(
547
548
  {
548
549
  Col.MODEL: String,
@@ -171,7 +171,7 @@ class DataBundle:
171
171
  X: NDArray[np.floating] = field(validator=is_ndarray)
172
172
  y: NDArray[np.floating] = field(validator=is_ndarray)
173
173
  X_names: tuple[str, ...] = field(converter=to_tuple)
174
- y_name: str
174
+ y_name: str = field(validator=validators.instance_of(str))
175
175
 
176
176
  valid_mask: NDArray[np.bool_] = field(validator=is_ndarray)
177
177
  n_total: int = field(validator=validators.instance_of(int))