Skip to content

Commit 530954d

Browse files
author
miranov25
committed
PHASE 13.41.DF — N-D Faceting via facet_by=List[str]
[Full v1.6 commit message preserved + CRR §2 disclosures:] Fix-at-code-time disclosures (CRR §2): §2.1: DFDraw.profile uses range= (not x_range=) — remaps internally to draw_profile's x_range=. v1.4 CP1-1 spec referenced draw_profile level only. §2.2: matplotlib range= controls BIN range, not axis xlim. For share_across_figures=True, also call ax.set_xlim post-draw for hist/profile (matches scatter pattern). FBY.16 lock. §2.3: Internal lock params renamed _lock_x_range/_lock_y_range to avoid collision with user x_range in plot_kwargs. §2.4: scatter has no auto_title param (drawer.py:1198); auto_title added only for hist/profile in inner dispatch. §2.5: _compute_global_ranges uses y_expr for hist (hist convention: x_expr=None, histogrammed column is in y_expr). Scope deferred (Phase 13.41 FIX1): - DFDraw.* signature type hints for facet_by Union[str, List[str]] - DFDraw.* named params for share_x/share_y/share_across_figures - _*_FORWARDED_NAMES updates (Functional behavior complete; documentation polish deferred.) Tests: 923 → 942 (+19 §9 invariance: FBY.1-19).
1 parent 67d125e commit 530954d

5 files changed

Lines changed: 1054 additions & 7 deletions

File tree

UTILS/dfextensions/dfdraw/docs/CAPABILITY_MATRIX.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Capability Matrix — dfdraw
22

3-
**Generated:** 2026-05-21 22:27 UTC
3+
**Generated:** 2026-05-23 07:18 UTC
44
**Phase:** 13.15.DF
55
**Generator:** `scripts/generate_capability_matrix.py`
66
**Sources:** `tests/feature_taxonomy.py` + `tests/test_layer_classification.py`
@@ -9,13 +9,13 @@
99

1010
| Status | Count | % |
1111
|--------|------:|--:|
12-
| ✅ Verified | 48 | 45% |
13-
| ☑️ Smoke-only | 57 | 54% |
12+
| ✅ Verified | 49 | 46% |
13+
| ☑️ Smoke-only | 57 | 53% |
1414
| 🧨 Broken | 0 | 0% |
1515
| 📋 Planned | 1 | 1% |
16-
| **Total features** | **106** | |
17-
| **Total proof tests** | **478** | |
18-
| **Invariance tests** | **249** | |
16+
| **Total features** | **107** | |
17+
| **Total proof tests** | **497** | |
18+
| **Invariance tests** | **268** | |
1919

2020
**Status key:**
2121
- ✅ Verified — has at least one invariance test (A ≡ B check)
@@ -169,6 +169,8 @@
169169
|| **SCATTER.scatter3d** — draw('z:y:x', type='scatter3d') → 3D point cloud via mpl_toolkits.mplot3d. Reuses Phase 13.38 _process_color() + _process_size() unchanged. color=/size= accept column names or df.eval() expressions. elev=/azim= for ax.view_init(). Stats dict locks mean_x AND mean_y AND mean_z to 1e-9 (CP1-3). Scope boundaries: group_by + scatter3d raises (CP2-1); same=True onto non-3D axes raises (CP2-2). 'y:x' (colon!=2) with type='scatter3d' raises with actionable message — Phase 13.39.DF | 8 | 0 |
170170
| | **HIST** | | |
171171
|| **HIST.cumulative** — hist() cumulative=True/-1/False — ROOT TH1::Draw('cumulative') equivalent. Three values: True (ascending CDF/ECDF), False (default, byte-identical backward compat), -1 (descending/survival, ROOT convention). matplotlib native cumulative= forwarded explicitly at 4 internal call sites (Phase 13.39 §2.2 lesson applied recursively: DFDraw.hist → draw_hist → _draw_hist_grouped → ax.hist; ALSO through _dispatch_faceted_render for facet_by composition). Composes with: norm='probability' (→ ECDF 0-1), group_by overlaid (per-group ECDFs), group_by stacked (CP2-1 regression lock for 3rd call site), facet_by (per-facet cumulative), histtype='step' (HEP-standard step ECDF). Correctness guard (M5): hist_errors+cumulative → NotImplementedError (Poisson per-bin errors are independent; cumulative counts are correlated). Vector dispatch [x,y] propagates cumulative correctly (Phase 13.16.DF FIX1 bug class lock) — Phase 13.40.DF | 10 | 0 |
172+
| | **FACET** | | |
173+
| ✅ | **FACET.list_grid** — facet_by accepts Union[str, List[str]] for 1D/2D/3D faceting. Convention LOCKED matching numpy/pandas (n_rows, n_cols, ...) shape: facet_by[0]=ROW (vertical within figure), facet_by[1]=COLUMN (horizontal within figure), facet_by[2]=FIGID (separate figures, one per value). facet_by[3+] raises NotImplementedError. 3D returns (List[Figure], List[axes_2d], List[stats_dict]) — DEVIATES from standard (fig, ax, stats) contract; documented prominently in inline help. New params: share_x/share_y ∈ {'all','row','col','none'} (within-figure axis sharing), share_across_figures: bool (3D global range lock). Per-plot-kind lock for share_across_figures (CP1-2): scatter locks x AND y; hist/profile locks x only (y auto-scales per figure to handle sparse-figID variance). New helpers: _normalize_facet_args, _to_mpl_share (symmetric {'all':True,'row':'row','col':'col','none':False} — v1.2 CP0-1 fix for Hard Constraint #3), _validate_share_axis_value, _resolve_facet_values (discrete or pd.cut/qcut Interval), _filter_facet_value (CP1-3 discrete vs binned), _compute_global_ranges. dfdraw is FIRST major plotting library with unified API where Nth faceting dimension generates separate figures (seaborn/ggplot2/plotly/altair all require manual loops). _validate_facet_by_binning guard for list input (v1.3 P1-A). Per-plot-kind dispatch: hist uses range= (matplotlib convention); profile uses range= which DFDraw.profile remaps to draw_profile's x_range= internally; scatter uses ax.set_xlim/set_ylim post-draw (no native range params); hist also locks ax.set_xlim post-draw (range= only locks bins, not axis xlim). Empty cell handling: '(no data)' diagnostic + stats={'n':0,'empty':True} — Phase 13.41.DF | 19 | 0 |
172174

173175
---
174176

0 commit comments

Comments
 (0)