|
1 | | -# 0.22.0 (Unreleased - TBD) |
2 | | - |
3 | | -## New Features |
4 | | - |
5 | | -- **CLI `--formula` now accepts JSON lists for model-matrix formula lists.** |
6 | | - In addition to a single formula string, CLI users can pass values such as |
7 | | - `--formula='["age", "gender"]'`, which are parsed and forwarded as |
8 | | - `list[str]` to IPW/CBPS model-matrix construction. Malformed, empty, or |
9 | | - non-string JSON lists now fail during argument parsing. |
10 | | - |
11 | | -# 0.21.0 (2026-05-29) |
| 1 | +# 0.21.0 (2026-06-02) |
12 | 2 |
|
13 | 3 | ## New Features |
14 | 4 |
|
|
29 | 19 | threshold default resolving to the cobalt 0.1 cutoff for ASMD only. |
30 | 20 | `.plot(dist_type="love_plot", library=...)` (or the `"love"` alias) routes |
31 | 21 | covariate views to the same diagnostic. |
32 | | - |
33 | 22 | - **Rake now supports fit-time metadata persistence and `predict_weights()` |
34 | 23 | reconstruction.** |
35 | 24 | - `rake(..., store_fit_metadata=True)` stores contingency-table artifacts |
|
44 | 33 | `transformations="default"` and for explicit dicts that directly |
45 | 34 | reference data-dependent helpers (`quantize`, `fct_lump`). Pass |
46 | 35 | deterministic transformations at fit time or re-fit on the scoring data. |
47 | | - |
48 | 36 | - **Poststratify now supports transfer scoring with `predict_weights(data=...)`.** |
49 | 37 | `BalanceFrame.fit(method="poststratify", store_fit_metadata=True)` stores |
50 | 38 | the transformation origin needed to safely replay fitted cell ratios on a |
|
54 | 42 | `transformations="default"` and direct `quantize` / `fct_lump` references. |
55 | 43 | Pre-0.21.0 pickles lack `transformations_origin` and must be re-fit for |
56 | 44 | transfer scoring; in-place `predict_weights()` continues to work. |
57 | | - |
58 | 45 | - **`balance.interop.diff_diff`** — thin adapter to |
59 | 46 | [diff-diff](https://github.com/igerber/diff-diff) (`>=3.3.0,<4`) for |
60 | 47 | survey-weighted Difference-in-Differences. Provides `to_survey_design()`, |
|
67 | 54 | live in `balance/interop/_common.py` and column-name conventions in |
68 | 55 | `balance/interop/conventions.py` so a future `balance.interop.svy` adapter |
69 | 56 | can reuse them. |
70 | | - |
71 | 57 | - **`balance.stats_and_plots.weights_stats.kish_deff_stats`** — bundled |
72 | 58 | Kish-design-effect diagnostic returning a `KishStats(deff, ess, essp)` |
73 | 59 | namedtuple. Computes `design_effect` once and derives ESS and ESSP from it, |
|
76 | 62 | over the existing `design_effect`. `BalanceFrame._design_effect_diagnostics` |
77 | 63 | now routes through `kish_deff_stats` so the canonical Kish identities live |
78 | 64 | in one place. |
79 | | - |
80 | 65 | - **`BalanceFrame.adjustment_history` records compound adjustment steps.** |
81 | 66 | Sequential `adjust()` / `set_fitted_model()` workflows now keep a |
82 | 67 | chronological, best-effort read-only copy of each adjustment step while |
83 | 68 | preserving `model` as the latest fitted model for backwards compatibility. |
84 | 69 | Baseline resets such as `set_as_pre_adjust()` clear the history together |
85 | 70 | with the current model. |
86 | | - |
87 | | -- **All-zero weight inputs to `_check_weights_series_are_valid` now emit a |
88 | | - `UserWarning`** (when `require_positive=False`, the default). Previously, |
89 | | - weighted statistics over an all-zero weight vector silently produced `NaN` / |
90 | | - `inf` (`sum(w*x)/sum(w) = 0/0`). Callers that already passed |
91 | | - `require_positive=True` (e.g. `design_effect`, `nonparametric_skew`, |
92 | | - `prop_above_and_below`, `weighted_median_breakdown_point`) keep their |
93 | | - `ValueError` behaviour. This affects internal callers like |
94 | | - `descriptive_stats` → `asmd`, which previously masked the failure mode. |
95 | | - |
96 | | -- Removed the scheduled migration `FutureWarning`s from `SampleFrame.weight_column`, |
97 | | - `SampleFrame.id_column`, and `BalanceFrame.id_column`; the accessors continue to return |
98 | | - column names, while `weight_series` and `id_series` return data. |
| 71 | +- **CLI `--formula` now accepts JSON lists for model-matrix formula lists.** |
| 72 | + In addition to a single formula string, CLI users can pass values such as |
| 73 | + `--formula='["age", "gender"]'`, which are parsed and forwarded as |
| 74 | + `list[str]` to IPW/CBPS model-matrix construction. Malformed, empty, or |
| 75 | + non-string JSON lists now fail during argument parsing. |
99 | 76 |
|
100 | 77 | ## Bug Fixes |
101 | 78 |
|
|
106 | 83 | matching `poststratify` semantics and ensuring weighted marginals recover |
107 | 84 | the target distribution when design weights are non-uniform. No-op when |
108 | 85 | design weights are uniform (the common case). |
109 | | - |
110 | 86 | - **`rake()` now gracefully handles single-variable adjustments.** When |
111 | 87 | `rake(...)` resolves to exactly one adjustment variable, it logs a warning |
112 | 88 | and delegates to `poststratify(...)` instead of raising an assertion. This |
|
115 | 91 | `BalanceFrame.fit(method="rake")` more robust for one-variable inputs. In |
116 | 92 | this delegated path, model metadata records `method='poststratify'` while |
117 | 93 | returned weights keep the canonical `rake_weight` name. |
118 | | - |
119 | 94 | - **CLI `--num_lambdas` now parses as a positive integer.** Fractional, |
120 | 95 | zero, negative, and non-numeric values fail fast during argument parsing |
121 | 96 | instead of being accepted after coercion/truncation or failing later |
122 | 97 | during IPW adjustment. |
123 | | - |
124 | 98 | - **Validation-path cleanup in `asmd`, `poststratify`, and `rake`** removes |
125 | 99 | redundant/unreachable branches with no behavior loss: |
126 | 100 | - `asmd(...)` uses a single authoritative invalid-`std_type` error path |
|
131 | 105 | `_cell_ratio_tmp`, `_cell_ratio_tmp2`, ...). |
132 | 106 | - `rake._predict_weights_from_model(...)` uses already-validated fit-time |
133 | 107 | target weights directly for non-transfer replay. |
134 | | - |
135 | 108 | - **Security: `ws` updated from 8.20.0 to 8.20.1** in website dependencies. |
136 | 109 | Fixes CVE-2026-45736 (GHSA-58qx-3vcg-4xpx): uninitialized memory disclosure |
137 | 110 | in `websocket.close()` when a `TypedArray` is passed as the reason argument. |
|
147 | 120 | (`HomepageFeatures.js`) gain matching cross-references; |
148 | 121 | `.github/copilot-instructions.md` gets a new review-checklist bullet for |
149 | 122 | changes that touch `balance/interop/diff_diff.py`. |
150 | | - |
151 | 123 | - **Survey-weighted DiD tutorial.** New |
152 | 124 | `tutorials/balance_diff_diff_brfss.ipynb` walks through a BRFSS-style |
153 | 125 | staggered-adoption smoking-ban DiD use case end-to-end: load synthetic |
|
162 | 134 |
|
163 | 135 | ## Code Quality & Refactoring |
164 | 136 |
|
| 137 | +- **All-zero weight inputs to `_check_weights_series_are_valid` now emit a |
| 138 | + `UserWarning`** (when `require_positive=False`, the default). Previously, |
| 139 | + weighted statistics over an all-zero weight vector silently produced `NaN` / |
| 140 | + `inf` (`sum(w*x)/sum(w) = 0/0`). Callers that already passed |
| 141 | + `require_positive=True` (e.g. `design_effect`, `nonparametric_skew`, |
| 142 | + `prop_above_and_below`, `weighted_median_breakdown_point`) keep their |
| 143 | + `ValueError` behaviour. This affects internal callers like |
| 144 | + `descriptive_stats` → `asmd`, which previously masked the failure mode. |
| 145 | +- Removed the scheduled migration `FutureWarning`s from `SampleFrame.weight_column`, |
| 146 | + `SampleFrame.id_column`, and `BalanceFrame.id_column`; the accessors continue to return |
| 147 | + column names, while `weight_series` and `id_series` return data. |
165 | 148 | - Diagnostics construction now wires `adjustment_failure` metadata from model |
166 | 149 | outputs when available (instead of hardcoding success), and supports an |
167 | 150 | optional `adjustment_failure_reason` diagnostics row for richer failure |
|
175 | 158 | - Expanded targeted test coverage for predict-time metadata validation, |
176 | 159 | replay/transfer edge cases, and error/warning paths in |
177 | 160 | `weighted_comparisons_stats`, `poststratify`, and `rake`. |
178 | | - |
179 | 161 | - **CI matrix entry for diff-diff integration.** The `Build and Test` workflow |
180 | 162 | exercises `tests/test_interop_diff_diff.py` on Python 3.12 against both the |
181 | 163 | minimum pin (`==3.3.0`) and the resolved-latest within `>=3.3.0,<4`, via |
|
0 commit comments