shaply 1.0.0__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 (35) hide show
  1. shaply-1.0.0/PKG-INFO +211 -0
  2. shaply-1.0.0/README.md +178 -0
  3. shaply-1.0.0/pyproject.toml +137 -0
  4. shaply-1.0.0/src/shaply/__init__.py +110 -0
  5. shaply-1.0.0/src/shaply/colors.py +96 -0
  6. shaply-1.0.0/src/shaply/config.py +241 -0
  7. shaply-1.0.0/src/shaply/enums.py +69 -0
  8. shaply-1.0.0/src/shaply/explanation.py +279 -0
  9. shaply-1.0.0/src/shaply/interaction.py +98 -0
  10. shaply-1.0.0/src/shaply/plots/__init__.py +52 -0
  11. shaply-1.0.0/src/shaply/plots/_common/__init__.py +8 -0
  12. shaply-1.0.0/src/shaply/plots/_common/cluster.py +122 -0
  13. shaply-1.0.0/src/shaply/plots/_common/layout.py +42 -0
  14. shaply-1.0.0/src/shaply/plots/_common/ordering.py +130 -0
  15. shaply-1.0.0/src/shaply/plots/_common/stats.py +42 -0
  16. shaply-1.0.0/src/shaply/plots/advanced/__init__.py +32 -0
  17. shaply-1.0.0/src/shaply/plots/advanced/beeswarm_ranges.py +197 -0
  18. shaply-1.0.0/src/shaply/plots/advanced/error_analysis.py +151 -0
  19. shaply-1.0.0/src/shaply/plots/advanced/explanation_archetypes.py +116 -0
  20. shaply-1.0.0/src/shaply/plots/advanced/feature_clustering.py +115 -0
  21. shaply-1.0.0/src/shaply/plots/advanced/importance_by_cohort.py +146 -0
  22. shaply-1.0.0/src/shaply/plots/advanced/importance_ci.py +118 -0
  23. shaply-1.0.0/src/shaply/plots/advanced/interaction_heatmap.py +93 -0
  24. shaply-1.0.0/src/shaply/plots/advanced/monotonicity.py +108 -0
  25. shaply-1.0.0/src/shaply/plots/advanced/response_curve.py +200 -0
  26. shaply-1.0.0/src/shaply/plots/advanced/shap_surface.py +148 -0
  27. shaply-1.0.0/src/shaply/plots/usual/__init__.py +21 -0
  28. shaply-1.0.0/src/shaply/plots/usual/bar.py +111 -0
  29. shaply-1.0.0/src/shaply/plots/usual/beeswarm.py +214 -0
  30. shaply-1.0.0/src/shaply/plots/usual/decision.py +140 -0
  31. shaply-1.0.0/src/shaply/plots/usual/force.py +164 -0
  32. shaply-1.0.0/src/shaply/plots/usual/heatmap.py +104 -0
  33. shaply-1.0.0/src/shaply/plots/usual/scatter.py +122 -0
  34. shaply-1.0.0/src/shaply/plots/usual/waterfall.py +129 -0
  35. shaply-1.0.0/src/shaply/py.typed +0 -0
shaply-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,211 @@
1
+ Metadata-Version: 2.3
2
+ Name: shaply
3
+ Version: 1.0.0
4
+ Summary: Usual SHAP explainability figures rendered as interactive Plotly charts.
5
+ Keywords: shap,shapley,plotly,explainability,xai,machine-learning
6
+ Author: antoine126
7
+ Author-email: antoine126 <antoine.pagneux@neuf.fr>
8
+ License: MIT
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Topic :: Scientific/Engineering :: Visualization
15
+ Classifier: Typing :: Typed
16
+ Requires-Dist: numpy>=1.26
17
+ Requires-Dist: plotly>=5.20
18
+ Requires-Dist: pydantic>=2.6
19
+ Requires-Dist: pandas>=2.0 ; extra == 'examples'
20
+ Requires-Dist: scikit-learn>=1.4 ; extra == 'examples'
21
+ Requires-Dist: xgboost>=2.0 ; extra == 'examples'
22
+ Requires-Dist: lightgbm>=4.0 ; extra == 'examples'
23
+ Requires-Dist: shap>=0.45 ; extra == 'examples'
24
+ Requires-Dist: ipykernel>=6.29 ; extra == 'examples'
25
+ Requires-Dist: nbformat>=5.9 ; extra == 'examples'
26
+ Requires-Dist: pandas>=2.0 ; extra == 'pandas'
27
+ Requires-Python: >=3.12.7
28
+ Project-URL: Homepage, https://github.com/antoine126/shaply
29
+ Project-URL: Repository, https://github.com/antoine126/shaply
30
+ Provides-Extra: examples
31
+ Provides-Extra: pandas
32
+ Description-Content-Type: text/markdown
33
+
34
+ # shaply
35
+
36
+ **Usual SHAP explainability figures, rendered as interactive [Plotly](https://plotly.com/python/) charts.**
37
+
38
+ `shaply` reproduces the familiar figures from the [`shap`](https://github.com/shap/shap) library - bar, beeswarm, waterfall, dependence (scatter) and heatmap - but returns `plotly.graph_objects.Figure` objects instead of matplotlib axes, so the plots are interactive and embeddable out of the box.
39
+
40
+ It does **not** depend on `shap`: every plotting function accepts a `shap.Explanation`-like object, a raw NumPy array of SHAP values, or a pandas `DataFrame`.
41
+
42
+ ## Install
43
+
44
+ ```bash
45
+ uv add shaply
46
+ # or
47
+ pip install shaply
48
+ ```
49
+
50
+ ### Optional dependencies (extras)
51
+
52
+ `shaply` itself only needs `numpy`, `plotly` and `pydantic`. Extra features and
53
+ the example notebook pull in heavier packages, grouped as installable extras:
54
+
55
+ | Extra | Installs | Purpose |
56
+ | ------------ | ---------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
57
+ | `pandas` | `pandas` | Pass SHAP values as a`DataFrame` (column names become feature names) |
58
+ | `examples` | `scikit-learn`, `xgboost`, `lightgbm`, `shap`, `pandas`, `ipykernel`, `nbformat` | Everything needed to run[`examples/shaply_demo.ipynb`](examples/shaply_demo.ipynb) |
59
+
60
+ ```bash
61
+ uv add "shaply[pandas]" # DataFrame support
62
+ uv add "shaply[examples]" # run the demo notebook
63
+ # or with pip
64
+ pip install "shaply[examples]"
65
+ ```
66
+
67
+ ### Building the wheel from source (use the package without PyPI)
68
+
69
+ To build and install `shaply` straight from a clone of this repository, without going through PyPI:
70
+
71
+ ```bash
72
+ git clone https://github.com/antoine126/shaply.git
73
+ cd shaply
74
+ uv build --wheel # produces dist/shaply-<version>-py3-none-any.whl
75
+ ```
76
+
77
+ Then install the wheel wherever you need it:
78
+
79
+ ```bash
80
+ uv add /path/to/shaply/dist/shaply-<version>-py3-none-any.whl
81
+ # or with pip, in any environment
82
+ pip install /path/to/shaply/dist/shaply-<version>-py3-none-any.whl
83
+ ```
84
+
85
+ The wheel is self-contained (it ships `py.typed`, so type annotations reach the installed package) and does not require `uv` or the source tree at runtime.
86
+
87
+ ## Quick start
88
+
89
+ ```python
90
+ import shaply
91
+
92
+ # `explanation` can be a shap.Explanation, an ndarray, or a DataFrame
93
+ fig = shaply.beeswarm(explanation)
94
+ fig.show()
95
+
96
+ fig = shaply.bar(explanation)
97
+ fig = shaply.waterfall(explanation, sample_index=0)
98
+ fig = shaply.scatter(explanation, feature="income", color_feature="age")
99
+ fig = shaply.heatmap(explanation)
100
+ ```
101
+
102
+ Every function takes an optional typed config from `shaply.config`:
103
+
104
+ ```python
105
+ from shaply.config import BeeswarmConfig
106
+ from shaply.enums import ColorScale, FeatureOrdering
107
+
108
+ cfg = BeeswarmConfig(
109
+ max_display=15,
110
+ ordering=FeatureOrdering.IMPORTANCE,
111
+ color_scale=ColorScale.RED_BLUE,
112
+ )
113
+ fig = shaply.beeswarm(explanation, config=cfg)
114
+ ```
115
+
116
+ ## Available plots
117
+
118
+ | Function | SHAP equivalent | Purpose |
119
+ | -------------------- | ------------------------ | ------------------------------------ |
120
+ | `shaply.bar` | `shap.plots.bar` | Global feature importance |
121
+ | `shaply.beeswarm` | `shap.plots.beeswarm` | Summary of per-sample contributions |
122
+ | `shaply.waterfall` | `shap.plots.waterfall` | Single-prediction explanation |
123
+ | `shaply.scatter` | `shap.plots.scatter` | Dependence plot |
124
+ | `shaply.heatmap` | `shap.plots.heatmap` | SHAP values across instances |
125
+ | `shaply.force` | `shap.plots.force` | Additive force layout (one instance) |
126
+ | `shaply.decision` | `shap.decision_plot` | Cumulative decision paths |
127
+
128
+ ## Advanced tools - beyond the usual SHAP plots
129
+
130
+ These are `shaply`-only figures aimed at engineers and business-facing data scientists who want to *act* on SHAP, not just explain a model. They cross SHAP values with the real data to surface operating ranges, tipping points, coupled effects and failure drivers.
131
+
132
+ > **Read them as associational, not causal.** SHAP measures a feature's
133
+ > contribution to the *model's* output, not to reality. Wording is deliberately
134
+ > cautious ("associated with", "tipping point of the model") - a strong signal
135
+ > here is a lead to investigate, not a proven cause.
136
+
137
+ | Function | What it shows | Insight |
138
+ | --------------------------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
139
+ | `shaply.beeswarm_ranges` | Beeswarm**+** real value distribution (violin + box, true min/max) per feature | Read impact*and* concrete operating range on the same line |
140
+ | `shaply.response_curve` | Smoothed mean SHAP vs a feature's value, with a ±1 std band and auto-detected zero-crossings | The **tipping point** where a feature flips from lowering to raising the output |
141
+ | `shaply.interaction_heatmap` | Matrix of mean\|SHAP interaction\| between feature pairs | Which features**act together** (coupled effects), diagonal hidden by default |
142
+ | `shaply.error_analysis` | Mean SHAP per feature,**correct vs mis-predicted** cohorts, ranked by gap | What the model relies on differently**when it is wrong** |
143
+ | `shaply.shap_surface` | Mean SHAP of a feature over the 2D plane of two features | The**operating regions** where a feature helps or hurts, and how a second one modulates it |
144
+ | `shaply.importance_by_cohort` | `mean(\|SHAP\|)` per feature, split by cohort (explicit or quantile-binned) | A feature can**dominate in one regime** and be negligible in another |
145
+ | `shaply.feature_clustering` | Clustered heatmap of SHAP correlation between features | **Redundant** features (correlated SHAP) that could be dropped |
146
+ | `shaply.explanation_archetypes` | Mean SHAP profile of each k-means cluster of instances | The model's recurring**decision patterns / failure modes** |
147
+ | `shaply.importance_ci` | Global importance bars with**bootstrap confidence intervals** | Whether an importance ranking is**robust** or fragile |
148
+ | `shaply.monotonicity_check` | Spearman correlation between each feature's value and its SHAP | Clean**monotonic** effects vs suspicious non-monotonic ones (interaction/noise) |
149
+
150
+ ```python
151
+ # Beeswarm + real value ranges (needs feature values via data=...)
152
+ shaply.beeswarm_ranges(explanation).show()
153
+
154
+ # Response curve of one feature, with tipping-point detection
155
+ shaply.response_curve(explanation, "temperature").show()
156
+
157
+ # Pairwise interaction strength (needs SHAP *interaction* values)
158
+ inter = shap.TreeExplainer(model).shap_interaction_values(X) # (n, f, f) - pick a class if 4D
159
+ shaply.interaction_heatmap(inter, feature_names=list(X.columns)).show()
160
+
161
+ # What drives the model's mistakes
162
+ shaply.error_analysis(explanation, y_true=y_test, y_pred=model.predict(X_test)).show()
163
+
164
+ # 2D SHAP surface over a feature pair
165
+ shaply.shap_surface(explanation, "temperature", "pressure").show()
166
+
167
+ # Importance split by an operating regime (quantiles of another feature)
168
+ shaply.importance_by_cohort(explanation, by_feature="load").show()
169
+
170
+ # Redundant features (correlated SHAP), and typical decision patterns
171
+ shaply.feature_clustering(explanation).show()
172
+ shaply.explanation_archetypes(explanation).show()
173
+
174
+ # Robustness of the ranking, and monotonicity of each effect
175
+ shaply.importance_ci(explanation).show()
176
+ shaply.monotonicity_check(explanation).show()
177
+ ```
178
+
179
+ Each takes a typed config from `shaply.config` (e.g. `ResponseCurveConfig`,
180
+ `ShapSurfaceConfig`, `ImportanceByCohortConfig`, `FeatureClusteringConfig`,
181
+ `ExplanationArchetypesConfig`, `ImportanceCIConfig`, `MonotonicityConfig`).
182
+
183
+ The clustering and statistics behind these tools are implemented in pure NumPy,
184
+ so the advanced tools add **no runtime dependency** beyond `numpy`/`plotly`/`pydantic`.
185
+
186
+ ## Example notebook
187
+
188
+ [`examples/shaply_demo.ipynb`](examples/shaply_demo.ipynb) is a full, executed walkthrough. It builds a **synthetic dataset** with `make_classification` (5 informative, 2 redundant and 3 pure-noise features), trains **five very different classifiers** - RandomForest, XGBoost, LightGBM, LogisticRegression and an RBF SVM - computes SHAP values for each (`TreeExplainer`, `LinearExplainer`, `KernelExplainer`) and renders **every `shaply` figure** for all of them, plus the advanced tools (response curve, interaction heatmap, error analysis) and a cross-model importance comparison.
189
+
190
+ ```bash
191
+ uv sync --extra examples
192
+ uv run jupyter lab examples/shaply_demo.ipynb
193
+ # regenerate the executed outputs from scratch:
194
+ uv run jupyter nbconvert --to notebook --execute --inplace examples/shaply_demo.ipynb
195
+ ```
196
+
197
+ ## Development
198
+
199
+ ```bash
200
+ uv sync
201
+ uv run ruff check . --fix
202
+ uv run ruff format .
203
+ uv run mypy
204
+ uv run pytest
205
+ ```
206
+
207
+ The package ships a `py.typed` marker, so all type annotations are available to downstream users.
208
+
209
+ ## License
210
+
211
+ MIT
shaply-1.0.0/README.md ADDED
@@ -0,0 +1,178 @@
1
+ # shaply
2
+
3
+ **Usual SHAP explainability figures, rendered as interactive [Plotly](https://plotly.com/python/) charts.**
4
+
5
+ `shaply` reproduces the familiar figures from the [`shap`](https://github.com/shap/shap) library - bar, beeswarm, waterfall, dependence (scatter) and heatmap - but returns `plotly.graph_objects.Figure` objects instead of matplotlib axes, so the plots are interactive and embeddable out of the box.
6
+
7
+ It does **not** depend on `shap`: every plotting function accepts a `shap.Explanation`-like object, a raw NumPy array of SHAP values, or a pandas `DataFrame`.
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ uv add shaply
13
+ # or
14
+ pip install shaply
15
+ ```
16
+
17
+ ### Optional dependencies (extras)
18
+
19
+ `shaply` itself only needs `numpy`, `plotly` and `pydantic`. Extra features and
20
+ the example notebook pull in heavier packages, grouped as installable extras:
21
+
22
+ | Extra | Installs | Purpose |
23
+ | ------------ | ---------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
24
+ | `pandas` | `pandas` | Pass SHAP values as a`DataFrame` (column names become feature names) |
25
+ | `examples` | `scikit-learn`, `xgboost`, `lightgbm`, `shap`, `pandas`, `ipykernel`, `nbformat` | Everything needed to run[`examples/shaply_demo.ipynb`](examples/shaply_demo.ipynb) |
26
+
27
+ ```bash
28
+ uv add "shaply[pandas]" # DataFrame support
29
+ uv add "shaply[examples]" # run the demo notebook
30
+ # or with pip
31
+ pip install "shaply[examples]"
32
+ ```
33
+
34
+ ### Building the wheel from source (use the package without PyPI)
35
+
36
+ To build and install `shaply` straight from a clone of this repository, without going through PyPI:
37
+
38
+ ```bash
39
+ git clone https://github.com/antoine126/shaply.git
40
+ cd shaply
41
+ uv build --wheel # produces dist/shaply-<version>-py3-none-any.whl
42
+ ```
43
+
44
+ Then install the wheel wherever you need it:
45
+
46
+ ```bash
47
+ uv add /path/to/shaply/dist/shaply-<version>-py3-none-any.whl
48
+ # or with pip, in any environment
49
+ pip install /path/to/shaply/dist/shaply-<version>-py3-none-any.whl
50
+ ```
51
+
52
+ The wheel is self-contained (it ships `py.typed`, so type annotations reach the installed package) and does not require `uv` or the source tree at runtime.
53
+
54
+ ## Quick start
55
+
56
+ ```python
57
+ import shaply
58
+
59
+ # `explanation` can be a shap.Explanation, an ndarray, or a DataFrame
60
+ fig = shaply.beeswarm(explanation)
61
+ fig.show()
62
+
63
+ fig = shaply.bar(explanation)
64
+ fig = shaply.waterfall(explanation, sample_index=0)
65
+ fig = shaply.scatter(explanation, feature="income", color_feature="age")
66
+ fig = shaply.heatmap(explanation)
67
+ ```
68
+
69
+ Every function takes an optional typed config from `shaply.config`:
70
+
71
+ ```python
72
+ from shaply.config import BeeswarmConfig
73
+ from shaply.enums import ColorScale, FeatureOrdering
74
+
75
+ cfg = BeeswarmConfig(
76
+ max_display=15,
77
+ ordering=FeatureOrdering.IMPORTANCE,
78
+ color_scale=ColorScale.RED_BLUE,
79
+ )
80
+ fig = shaply.beeswarm(explanation, config=cfg)
81
+ ```
82
+
83
+ ## Available plots
84
+
85
+ | Function | SHAP equivalent | Purpose |
86
+ | -------------------- | ------------------------ | ------------------------------------ |
87
+ | `shaply.bar` | `shap.plots.bar` | Global feature importance |
88
+ | `shaply.beeswarm` | `shap.plots.beeswarm` | Summary of per-sample contributions |
89
+ | `shaply.waterfall` | `shap.plots.waterfall` | Single-prediction explanation |
90
+ | `shaply.scatter` | `shap.plots.scatter` | Dependence plot |
91
+ | `shaply.heatmap` | `shap.plots.heatmap` | SHAP values across instances |
92
+ | `shaply.force` | `shap.plots.force` | Additive force layout (one instance) |
93
+ | `shaply.decision` | `shap.decision_plot` | Cumulative decision paths |
94
+
95
+ ## Advanced tools - beyond the usual SHAP plots
96
+
97
+ These are `shaply`-only figures aimed at engineers and business-facing data scientists who want to *act* on SHAP, not just explain a model. They cross SHAP values with the real data to surface operating ranges, tipping points, coupled effects and failure drivers.
98
+
99
+ > **Read them as associational, not causal.** SHAP measures a feature's
100
+ > contribution to the *model's* output, not to reality. Wording is deliberately
101
+ > cautious ("associated with", "tipping point of the model") - a strong signal
102
+ > here is a lead to investigate, not a proven cause.
103
+
104
+ | Function | What it shows | Insight |
105
+ | --------------------------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
106
+ | `shaply.beeswarm_ranges` | Beeswarm**+** real value distribution (violin + box, true min/max) per feature | Read impact*and* concrete operating range on the same line |
107
+ | `shaply.response_curve` | Smoothed mean SHAP vs a feature's value, with a ±1 std band and auto-detected zero-crossings | The **tipping point** where a feature flips from lowering to raising the output |
108
+ | `shaply.interaction_heatmap` | Matrix of mean\|SHAP interaction\| between feature pairs | Which features**act together** (coupled effects), diagonal hidden by default |
109
+ | `shaply.error_analysis` | Mean SHAP per feature,**correct vs mis-predicted** cohorts, ranked by gap | What the model relies on differently**when it is wrong** |
110
+ | `shaply.shap_surface` | Mean SHAP of a feature over the 2D plane of two features | The**operating regions** where a feature helps or hurts, and how a second one modulates it |
111
+ | `shaply.importance_by_cohort` | `mean(\|SHAP\|)` per feature, split by cohort (explicit or quantile-binned) | A feature can**dominate in one regime** and be negligible in another |
112
+ | `shaply.feature_clustering` | Clustered heatmap of SHAP correlation between features | **Redundant** features (correlated SHAP) that could be dropped |
113
+ | `shaply.explanation_archetypes` | Mean SHAP profile of each k-means cluster of instances | The model's recurring**decision patterns / failure modes** |
114
+ | `shaply.importance_ci` | Global importance bars with**bootstrap confidence intervals** | Whether an importance ranking is**robust** or fragile |
115
+ | `shaply.monotonicity_check` | Spearman correlation between each feature's value and its SHAP | Clean**monotonic** effects vs suspicious non-monotonic ones (interaction/noise) |
116
+
117
+ ```python
118
+ # Beeswarm + real value ranges (needs feature values via data=...)
119
+ shaply.beeswarm_ranges(explanation).show()
120
+
121
+ # Response curve of one feature, with tipping-point detection
122
+ shaply.response_curve(explanation, "temperature").show()
123
+
124
+ # Pairwise interaction strength (needs SHAP *interaction* values)
125
+ inter = shap.TreeExplainer(model).shap_interaction_values(X) # (n, f, f) - pick a class if 4D
126
+ shaply.interaction_heatmap(inter, feature_names=list(X.columns)).show()
127
+
128
+ # What drives the model's mistakes
129
+ shaply.error_analysis(explanation, y_true=y_test, y_pred=model.predict(X_test)).show()
130
+
131
+ # 2D SHAP surface over a feature pair
132
+ shaply.shap_surface(explanation, "temperature", "pressure").show()
133
+
134
+ # Importance split by an operating regime (quantiles of another feature)
135
+ shaply.importance_by_cohort(explanation, by_feature="load").show()
136
+
137
+ # Redundant features (correlated SHAP), and typical decision patterns
138
+ shaply.feature_clustering(explanation).show()
139
+ shaply.explanation_archetypes(explanation).show()
140
+
141
+ # Robustness of the ranking, and monotonicity of each effect
142
+ shaply.importance_ci(explanation).show()
143
+ shaply.monotonicity_check(explanation).show()
144
+ ```
145
+
146
+ Each takes a typed config from `shaply.config` (e.g. `ResponseCurveConfig`,
147
+ `ShapSurfaceConfig`, `ImportanceByCohortConfig`, `FeatureClusteringConfig`,
148
+ `ExplanationArchetypesConfig`, `ImportanceCIConfig`, `MonotonicityConfig`).
149
+
150
+ The clustering and statistics behind these tools are implemented in pure NumPy,
151
+ so the advanced tools add **no runtime dependency** beyond `numpy`/`plotly`/`pydantic`.
152
+
153
+ ## Example notebook
154
+
155
+ [`examples/shaply_demo.ipynb`](examples/shaply_demo.ipynb) is a full, executed walkthrough. It builds a **synthetic dataset** with `make_classification` (5 informative, 2 redundant and 3 pure-noise features), trains **five very different classifiers** - RandomForest, XGBoost, LightGBM, LogisticRegression and an RBF SVM - computes SHAP values for each (`TreeExplainer`, `LinearExplainer`, `KernelExplainer`) and renders **every `shaply` figure** for all of them, plus the advanced tools (response curve, interaction heatmap, error analysis) and a cross-model importance comparison.
156
+
157
+ ```bash
158
+ uv sync --extra examples
159
+ uv run jupyter lab examples/shaply_demo.ipynb
160
+ # regenerate the executed outputs from scratch:
161
+ uv run jupyter nbconvert --to notebook --execute --inplace examples/shaply_demo.ipynb
162
+ ```
163
+
164
+ ## Development
165
+
166
+ ```bash
167
+ uv sync
168
+ uv run ruff check . --fix
169
+ uv run ruff format .
170
+ uv run mypy
171
+ uv run pytest
172
+ ```
173
+
174
+ The package ships a `py.typed` marker, so all type annotations are available to downstream users.
175
+
176
+ ## License
177
+
178
+ MIT
@@ -0,0 +1,137 @@
1
+ [project]
2
+ name = "shaply"
3
+ version = "1.0.0"
4
+ description = "Usual SHAP explainability figures rendered as interactive Plotly charts."
5
+ readme = "README.md"
6
+ license = { text = "MIT" }
7
+ authors = [
8
+ { name = "antoine126", email = "antoine.pagneux@neuf.fr" },
9
+ ]
10
+ keywords = ["shap", "shapley", "plotly", "explainability", "xai", "machine-learning"]
11
+ requires-python = ">=3.12.7"
12
+ classifiers = [
13
+ "Development Status :: 3 - Alpha",
14
+ "Intended Audience :: Science/Research",
15
+ "License :: OSI Approved :: MIT License",
16
+ "Programming Language :: Python :: 3.12",
17
+ "Programming Language :: Python :: 3.13",
18
+ "Topic :: Scientific/Engineering :: Visualization",
19
+ "Typing :: Typed",
20
+ ]
21
+ dependencies = [
22
+ "numpy>=1.26",
23
+ "plotly>=5.20",
24
+ "pydantic>=2.6",
25
+ ]
26
+
27
+ [project.optional-dependencies]
28
+ pandas = ["pandas>=2.0"]
29
+
30
+ # Everything needed to run the example notebook in `examples/`.
31
+ examples = [
32
+ "pandas>=2.0",
33
+ "scikit-learn>=1.4",
34
+ "xgboost>=2.0",
35
+ "lightgbm>=4.0",
36
+ "shap>=0.45",
37
+ "ipykernel>=6.29",
38
+ "nbformat>=5.9",
39
+ ]
40
+
41
+ [project.urls]
42
+ Homepage = "https://github.com/antoine126/shaply"
43
+ Repository = "https://github.com/antoine126/shaply"
44
+
45
+ [dependency-groups]
46
+ dev = [
47
+ "mypy>=1.10",
48
+ "nbconvert>=7.16",
49
+ "pandas>=2.0",
50
+ "pandas-stubs>=2.0",
51
+ "pytest>=8.2",
52
+ "pytest-cov>=5.0",
53
+ "ruff>=0.5",
54
+ ]
55
+
56
+ [build-system]
57
+ requires = ["uv_build>=0.9.8,<0.10.0"]
58
+ build-backend = "uv_build"
59
+
60
+ [tool.uv.build-backend]
61
+ module-name = "shaply"
62
+ module-root = "src"
63
+
64
+ # ------------------------------------------------------------------------------
65
+ # Ruff
66
+ # ------------------------------------------------------------------------------
67
+ [tool.ruff]
68
+ line-length = 100
69
+ target-version = "py312"
70
+ src = ["src", "tests"]
71
+ extend-exclude = ["examples"]
72
+
73
+ [tool.ruff.lint]
74
+ select = [
75
+ "E", # pycodestyle errors
76
+ "W", # pycodestyle warnings
77
+ "F", # pyflakes
78
+ "I", # isort
79
+ "N", # pep8-naming
80
+ "UP", # pyupgrade
81
+ "B", # flake8-bugbear
82
+ "C4", # flake8-comprehensions
83
+ "SIM", # flake8-simplify
84
+ "TC", # flake8-type-checking
85
+ "PTH", # flake8-use-pathlib
86
+ "RUF", # ruff-specific rules
87
+ "ANN", # flake8-annotations
88
+ "D", # pydocstyle
89
+ ]
90
+ ignore = [
91
+ "D105", # missing docstring in magic method
92
+ "D107", # missing docstring in __init__
93
+ "ANN401", # dynamically typed *args/**kwargs allowed where needed
94
+ ]
95
+
96
+ [tool.ruff.lint.per-file-ignores]
97
+ "tests/*" = ["D100", "D101", "D102", "D103", "D104", "ANN", "TC001", "TC002", "TC003"]
98
+
99
+ [tool.ruff.lint.pydocstyle]
100
+ convention = "numpy"
101
+
102
+ [tool.ruff.lint.isort]
103
+ known-first-party = ["shaply"]
104
+
105
+ # ------------------------------------------------------------------------------
106
+ # mypy
107
+ # ------------------------------------------------------------------------------
108
+ [tool.mypy]
109
+ python_version = "3.12"
110
+ strict = true
111
+ warn_unreachable = true
112
+ warn_redundant_casts = true
113
+ plugins = ["pydantic.mypy"]
114
+ files = ["src", "tests"]
115
+
116
+ [[tool.mypy.overrides]]
117
+ module = ["plotly.*"]
118
+ ignore_missing_imports = true
119
+
120
+ # ------------------------------------------------------------------------------
121
+ # pytest
122
+ # ------------------------------------------------------------------------------
123
+ [tool.pytest.ini_options]
124
+ minversion = "8.0"
125
+ addopts = "-ra --strict-markers --cov=shaply --cov-report=term-missing"
126
+ testpaths = ["tests"]
127
+
128
+ # ------------------------------------------------------------------------------
129
+ # coverage
130
+ # ------------------------------------------------------------------------------
131
+ [tool.coverage.report]
132
+ exclude_lines = [
133
+ "pragma: no cover",
134
+ "if TYPE_CHECKING:",
135
+ "raise NotImplementedError",
136
+ "@overload",
137
+ ]
@@ -0,0 +1,110 @@
1
+ """shaply - usual SHAP explainability figures rendered as Plotly charts.
2
+
3
+ The public API mirrors the familiar ``shap.plots`` entry points but returns
4
+ :class:`plotly.graph_objects.Figure` objects instead of matplotlib axes::
5
+
6
+ import shaply
7
+
8
+ fig = shaply.beeswarm(shap_values) # a shap.Explanation, ndarray or DataFrame
9
+ fig.show()
10
+
11
+ Every plotting function accepts a ``shap.Explanation``-like object, a numpy
12
+ array of SHAP values, or a :class:`pandas.DataFrame`, and an optional typed
13
+ config object from :mod:`shaply.config`.
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ from importlib.metadata import PackageNotFoundError, version
19
+
20
+ from shaply.config import (
21
+ BarConfig,
22
+ BeeswarmConfig,
23
+ BeeswarmRangesConfig,
24
+ DecisionConfig,
25
+ ErrorAnalysisConfig,
26
+ ExplanationArchetypesConfig,
27
+ FeatureClusteringConfig,
28
+ ForceConfig,
29
+ HeatmapConfig,
30
+ ImportanceByCohortConfig,
31
+ ImportanceCIConfig,
32
+ InteractionHeatmapConfig,
33
+ MonotonicityConfig,
34
+ ResponseCurveConfig,
35
+ ScatterConfig,
36
+ ShapSurfaceConfig,
37
+ WaterfallConfig,
38
+ )
39
+ from shaply.enums import ColorScale, FeatureOrdering, PlotType
40
+ from shaply.explanation import Explanation, to_explanation
41
+ from shaply.interaction import InteractionValues, to_interaction_values
42
+ from shaply.plots import (
43
+ bar,
44
+ beeswarm,
45
+ beeswarm_ranges,
46
+ decision,
47
+ error_analysis,
48
+ explanation_archetypes,
49
+ feature_clustering,
50
+ force,
51
+ heatmap,
52
+ importance_by_cohort,
53
+ importance_ci,
54
+ interaction_heatmap,
55
+ monotonicity_check,
56
+ response_curve,
57
+ scatter,
58
+ shap_surface,
59
+ waterfall,
60
+ )
61
+
62
+ try:
63
+ __version__ = version("shaply")
64
+ except PackageNotFoundError: # pragma: no cover - only during local dev without install
65
+ __version__ = "0.0.0"
66
+
67
+ __all__ = [
68
+ "BarConfig",
69
+ "BeeswarmConfig",
70
+ "BeeswarmRangesConfig",
71
+ "ColorScale",
72
+ "DecisionConfig",
73
+ "ErrorAnalysisConfig",
74
+ "Explanation",
75
+ "ExplanationArchetypesConfig",
76
+ "FeatureClusteringConfig",
77
+ "FeatureOrdering",
78
+ "ForceConfig",
79
+ "HeatmapConfig",
80
+ "ImportanceByCohortConfig",
81
+ "ImportanceCIConfig",
82
+ "InteractionHeatmapConfig",
83
+ "InteractionValues",
84
+ "MonotonicityConfig",
85
+ "PlotType",
86
+ "ResponseCurveConfig",
87
+ "ScatterConfig",
88
+ "ShapSurfaceConfig",
89
+ "WaterfallConfig",
90
+ "__version__",
91
+ "bar",
92
+ "beeswarm",
93
+ "beeswarm_ranges",
94
+ "decision",
95
+ "error_analysis",
96
+ "explanation_archetypes",
97
+ "feature_clustering",
98
+ "force",
99
+ "heatmap",
100
+ "importance_by_cohort",
101
+ "importance_ci",
102
+ "interaction_heatmap",
103
+ "monotonicity_check",
104
+ "response_curve",
105
+ "scatter",
106
+ "shap_surface",
107
+ "to_explanation",
108
+ "to_interaction_values",
109
+ "waterfall",
110
+ ]