abspc 0.2.1__py3-none-any.whl
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.
- abspc/README.md +514 -0
- abspc/__init__.py +58 -0
- abspc/icons/assurance_fail.png +0 -0
- abspc/icons/assurance_hit_or_miss.png +0 -0
- abspc/icons/assurance_pass.png +0 -0
- abspc/icons/icon_empty.png +0 -0
- abspc/icons/improvement_direction_high.png +0 -0
- abspc/icons/improvement_direction_low.png +0 -0
- abspc/icons/variation_common_cause.png +0 -0
- abspc/icons/variation_concern_high.png +0 -0
- abspc/icons/variation_concern_low.png +0 -0
- abspc/icons/variation_improvement_high.png +0 -0
- abspc/icons/variation_improvement_low.png +0 -0
- abspc/plot.py +1193 -0
- abspc/spc.py +1230 -0
- abspc/utils.py +484 -0
- abspc-0.2.1.dist-info/METADATA +571 -0
- abspc-0.2.1.dist-info/RECORD +21 -0
- abspc-0.2.1.dist-info/WHEEL +5 -0
- abspc-0.2.1.dist-info/licenses/LICENSE +21 -0
- abspc-0.2.1.dist-info/top_level.txt +1 -0
abspc/README.md
ADDED
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
# abspc — Python SPC Charts
|
|
2
|
+
|
|
3
|
+
The `abspc` Python package provides publication-ready Statistical Process
|
|
4
|
+
Control (SPC) charts following the NHS
|
|
5
|
+
[Making Data Count](https://www.england.nhs.uk/publication/making-data-count/)
|
|
6
|
+
methodology.
|
|
7
|
+
|
|
8
|
+
Built on **matplotlib**, it produces high-quality static images suitable for
|
|
9
|
+
board reports, dashboards, and quality-improvement publications.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pip install abspc
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Or install the development version from source:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
git clone https://github.com/Aneurin-Bevan-University-Health-Board/biu_Making_Data_Count_CustomVisuals
|
|
23
|
+
cd biu_Making_Data_Count_CustomVisuals
|
|
24
|
+
pip install -e ".[dev]"
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Quick Start
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
import pandas as pd
|
|
33
|
+
from abspc import plot_spc_chart, plot_run_chart
|
|
34
|
+
|
|
35
|
+
# Minimal XmR chart
|
|
36
|
+
data = pd.DataFrame({"value": [48, 52, 49, 55, 47, 51, 53, 50, 48, 54]})
|
|
37
|
+
fig, ax = plot_spc_chart(data, chart_type="XmR")
|
|
38
|
+
fig.savefig("my_xmr_chart.png")
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Chart Types
|
|
44
|
+
|
|
45
|
+
### XmR Chart
|
|
46
|
+
|
|
47
|
+
The XmR (individuals / moving-range) chart is the most common SPC chart type.
|
|
48
|
+
It is suitable for individual measurements collected over time.
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
import numpy as np
|
|
52
|
+
import pandas as pd
|
|
53
|
+
from abspc import plot_spc_chart
|
|
54
|
+
|
|
55
|
+
data = pd.DataFrame({"value": np.random.normal(50, 3, 24)})
|
|
56
|
+
|
|
57
|
+
fig, ax = plot_spc_chart(
|
|
58
|
+
data,
|
|
59
|
+
chart_type="XmR",
|
|
60
|
+
title="XmR Chart – Individual Measurements",
|
|
61
|
+
xlabel="Month",
|
|
62
|
+
ylabel="Value",
|
|
63
|
+
shade_band=True,
|
|
64
|
+
improvement_direction="high",
|
|
65
|
+
)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+

|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
### p Chart
|
|
73
|
+
|
|
74
|
+
The p chart is for proportion data (e.g., percentage of patients waiting
|
|
75
|
+
> 4 hours). It requires a `subgroup_size` column containing the denominator.
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
data = pd.DataFrame({
|
|
79
|
+
"value": [0.10, 0.12, 0.08, 0.15, 0.09, 0.11, 0.10, 0.13, 0.07, 0.12,
|
|
80
|
+
0.09, 0.11, 0.10, 0.08, 0.14, 0.12, 0.09, 0.11, 0.08, 0.10,
|
|
81
|
+
0.12, 0.09, 0.11, 0.10],
|
|
82
|
+
"subgroup_size": [200] * 24,
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
fig, ax = plot_spc_chart(
|
|
86
|
+
data,
|
|
87
|
+
chart_type="p",
|
|
88
|
+
title="p Chart – Proportion",
|
|
89
|
+
xlabel="Month",
|
|
90
|
+
ylabel="Proportion",
|
|
91
|
+
improvement_direction="low",
|
|
92
|
+
)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+

|
|
96
|
+
|
|
97
|
+
You can also pass a **numerator column** and a **denominator column**:
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
data = pd.DataFrame({
|
|
101
|
+
"events": [20, 24, 16, 30, 18],
|
|
102
|
+
"population": [200, 200, 200, 200, 200],
|
|
103
|
+
})
|
|
104
|
+
fig, ax = plot_spc_chart(
|
|
105
|
+
data,
|
|
106
|
+
chart_type="p",
|
|
107
|
+
value_col="population",
|
|
108
|
+
numerator_col="events",
|
|
109
|
+
improvement_direction="low",
|
|
110
|
+
)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
### c Chart
|
|
116
|
+
|
|
117
|
+
The c chart is for counts of events in a fixed sample size (e.g., adverse
|
|
118
|
+
events per ward per month).
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
data = pd.DataFrame({"value": [3, 5, 2, 6, 4, 3, 7, 5, 4, 6,
|
|
122
|
+
5, 3, 4, 6, 5, 4, 3, 5, 6, 4,
|
|
123
|
+
3, 5, 4, 6]})
|
|
124
|
+
|
|
125
|
+
fig, ax = plot_spc_chart(
|
|
126
|
+
data,
|
|
127
|
+
chart_type="c",
|
|
128
|
+
title="c Chart – Count of Events",
|
|
129
|
+
xlabel="Month",
|
|
130
|
+
ylabel="Count",
|
|
131
|
+
improvement_direction="low",
|
|
132
|
+
)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+

|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
### Run Chart
|
|
140
|
+
|
|
141
|
+
The run chart plots data against time with a **median** centre line and no
|
|
142
|
+
control limits. It uses run-chart rules to detect signals (8-point shift and
|
|
143
|
+
6-point trend).
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
from abspc import plot_run_chart
|
|
147
|
+
|
|
148
|
+
data = pd.DataFrame({"value": np.random.normal(40, 4, 24)})
|
|
149
|
+
|
|
150
|
+
fig, ax = plot_run_chart(
|
|
151
|
+
data,
|
|
152
|
+
title="Run Chart – Median Centre Line",
|
|
153
|
+
xlabel="Month",
|
|
154
|
+
ylabel="Value",
|
|
155
|
+
improvement_direction="high",
|
|
156
|
+
)
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+

|
|
160
|
+
|
|
161
|
+
`plot_spc_chart` also accepts `chart_type="run"` and will automatically
|
|
162
|
+
delegate to `plot_run_chart`:
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
fig, ax = plot_spc_chart(data, chart_type="run")
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Features
|
|
171
|
+
|
|
172
|
+
### Logo Placement
|
|
173
|
+
|
|
174
|
+
Pass any image (PNG, JPEG, etc.) via `logo_path` to display your
|
|
175
|
+
organisation's logo at the **top-right of the chart, level with the title**.
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
fig, ax = plot_spc_chart(
|
|
179
|
+
data,
|
|
180
|
+
chart_type="XmR",
|
|
181
|
+
title="A&E 4-Hour Waits – Aneurin Bevan UHB",
|
|
182
|
+
logo_path="path/to/logo.png",
|
|
183
|
+
logo_zoom=0.08,
|
|
184
|
+
)
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+

|
|
188
|
+
|
|
189
|
+
> **Note:** `logo_path` places the logo in the title margin (top-right).
|
|
190
|
+
> The legacy `nhs_logo_path` parameter places an image inside the plot area.
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
### Date Axis
|
|
195
|
+
|
|
196
|
+
All chart functions automatically detect datetime data on the x-axis and
|
|
197
|
+
apply smart date tick formatting.
|
|
198
|
+
|
|
199
|
+
**Option 1 — `DatetimeIndex` (auto-detected):**
|
|
200
|
+
|
|
201
|
+
```python
|
|
202
|
+
dates = pd.date_range("2022-01-01", periods=30, freq="MS")
|
|
203
|
+
data = pd.DataFrame({"value": np.random.normal(75, 6, 30)}, index=dates)
|
|
204
|
+
|
|
205
|
+
fig, ax = plot_spc_chart(data, chart_type="XmR", title="Monthly Date Axis")
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+

|
|
209
|
+
|
|
210
|
+
**Option 2 — Explicit date column:**
|
|
211
|
+
|
|
212
|
+
```python
|
|
213
|
+
fig, ax = plot_run_chart(data, x_col="period", date_format="%b %Y")
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
| `date_format` | Example output |
|
|
217
|
+
|---------------|----------------|
|
|
218
|
+
| `"%b %Y"` | Jan 2024 |
|
|
219
|
+
| `"%Y-%m"` | 2024-01 |
|
|
220
|
+
| `"%d/%m/%Y"` | 01/01/2024 |
|
|
221
|
+
| `None` *(default)* | Auto (ConciseDateFormatter) |
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
### Change-Point Annotations
|
|
226
|
+
|
|
227
|
+
Mark known process changes with vertical lines and labels:
|
|
228
|
+
|
|
229
|
+
```python
|
|
230
|
+
fig, ax = plot_spc_chart(
|
|
231
|
+
data,
|
|
232
|
+
chart_type="XmR",
|
|
233
|
+
change_points=[
|
|
234
|
+
{"x": 9, "label": "New protocol"},
|
|
235
|
+
{"x": 20, "label": "Staff training"},
|
|
236
|
+
],
|
|
237
|
+
)
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+

|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
### Auto-Rebase on Sustained Improvement
|
|
245
|
+
|
|
246
|
+
When ≥ 8 consecutive points show sustained improvement, control limits can be
|
|
247
|
+
automatically recalculated for the new phase:
|
|
248
|
+
|
|
249
|
+
```python
|
|
250
|
+
fig, ax = plot_spc_chart(
|
|
251
|
+
data,
|
|
252
|
+
chart_type="XmR",
|
|
253
|
+
improvement_direction="high",
|
|
254
|
+
auto_rebase=True,
|
|
255
|
+
)
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+

|
|
259
|
+
|
|
260
|
+
Use `rebase_control_limits` for programmatic access without plotting:
|
|
261
|
+
|
|
262
|
+
```python
|
|
263
|
+
from abspc import rebase_control_limits
|
|
264
|
+
|
|
265
|
+
result = rebase_control_limits(data, chart_type="XmR", improvement_direction="high")
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
> Auto-rebase is supported for XmR, p, u, and c charts (not run charts).
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
### MDC Variation & Assurance Icons
|
|
273
|
+
|
|
274
|
+
Set `show_icons=True` to display the official Making Data Count variation and
|
|
275
|
+
assurance icons at the top-left of the chart:
|
|
276
|
+
|
|
277
|
+
```python
|
|
278
|
+
fig, ax = plot_spc_chart(
|
|
279
|
+
data,
|
|
280
|
+
chart_type="XmR",
|
|
281
|
+
improvement_direction="high",
|
|
282
|
+
target=60,
|
|
283
|
+
show_target=True,
|
|
284
|
+
show_icons=True,
|
|
285
|
+
)
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
**Programmatic access:**
|
|
289
|
+
|
|
290
|
+
```python
|
|
291
|
+
from abspc import (
|
|
292
|
+
calculate_control_limits,
|
|
293
|
+
detect_special_causes,
|
|
294
|
+
determine_variation_type,
|
|
295
|
+
determine_assurance_type,
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
result = detect_special_causes(calculate_control_limits(data, chart_type="XmR"))
|
|
299
|
+
variation = determine_variation_type(result, value_col="value", improvement_direction="high")
|
|
300
|
+
assurance = determine_assurance_type(result, target=60, improvement_direction="high")
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
> For run charts only the variation icon is shown (no control limits means
|
|
304
|
+
> assurance cannot be calculated).
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
### MDC Summary Table
|
|
309
|
+
|
|
310
|
+
`plot_mdc_summary_table` renders an NHS MDC-style summary table showing
|
|
311
|
+
multiple measures at a glance:
|
|
312
|
+
|
|
313
|
+
```python
|
|
314
|
+
from abspc import plot_mdc_summary_table
|
|
315
|
+
|
|
316
|
+
fig, ax = plot_mdc_summary_table(
|
|
317
|
+
[
|
|
318
|
+
{
|
|
319
|
+
"data": df,
|
|
320
|
+
"chart_type": "XmR",
|
|
321
|
+
"measure": "A&E 4-Hour Waits",
|
|
322
|
+
"description": "% patients seen within 4 hours",
|
|
323
|
+
"value_col": "value",
|
|
324
|
+
"improvement_direction": "high",
|
|
325
|
+
"target": 95,
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
"data": df_infections,
|
|
329
|
+
"chart_type": "p",
|
|
330
|
+
"measure": "Infection Rate",
|
|
331
|
+
"description": "Proportion of infections per month",
|
|
332
|
+
"value_col": "value",
|
|
333
|
+
"improvement_direction": "low",
|
|
334
|
+
"target": 0.05,
|
|
335
|
+
"subgroup_col": "subgroup_size",
|
|
336
|
+
},
|
|
337
|
+
],
|
|
338
|
+
title="MDC Summary — Board Report",
|
|
339
|
+
)
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
## Special-Cause Rules
|
|
345
|
+
|
|
346
|
+
Four NHS MDC rules (aligned with NHSRplotthedots):
|
|
347
|
+
|
|
348
|
+
| Rule | Name | Description |
|
|
349
|
+
|------|------|-------------|
|
|
350
|
+
| **1** | Astronomical point | Single value outside 3σ limits |
|
|
351
|
+
| **2** | Shift | ≥ 8 consecutive points above or below the mean |
|
|
352
|
+
| **3** | Trend | ≥ 6 consecutive points all rising or all falling |
|
|
353
|
+
| **4** | Two-in-three | 2 of 3 consecutive points in the warning zone |
|
|
354
|
+
|
|
355
|
+
Use the detection functions directly:
|
|
356
|
+
|
|
357
|
+
```python
|
|
358
|
+
from abspc import calculate_control_limits, detect_special_causes
|
|
359
|
+
|
|
360
|
+
result = calculate_control_limits(data, chart_type="XmR")
|
|
361
|
+
flags = detect_special_causes(result)
|
|
362
|
+
print(flags[["value", "mean", "ucl", "lcl", "rule1", "rule2", "rule3", "rule4", "special_cause"]])
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
## API Reference
|
|
368
|
+
|
|
369
|
+
### `plot_spc_chart`
|
|
370
|
+
|
|
371
|
+
```python
|
|
372
|
+
fig, ax = plot_spc_chart(
|
|
373
|
+
data,
|
|
374
|
+
chart_type, # "XmR" | "p" | "u" | "c" | "run"
|
|
375
|
+
value_col="value",
|
|
376
|
+
subgroup_col="subgroup_size",
|
|
377
|
+
numerator_col=None,
|
|
378
|
+
x_col=None,
|
|
379
|
+
title=None,
|
|
380
|
+
xlabel="Observation",
|
|
381
|
+
ylabel="Value",
|
|
382
|
+
improvement_direction="high",
|
|
383
|
+
target=None,
|
|
384
|
+
show_target=False,
|
|
385
|
+
shade_band=False,
|
|
386
|
+
shade_color="#41B6E6",
|
|
387
|
+
nhs_logo_path=None,
|
|
388
|
+
ax=None,
|
|
389
|
+
figsize=(12, 5),
|
|
390
|
+
show_legend=True,
|
|
391
|
+
change_points=None,
|
|
392
|
+
auto_rebase=False,
|
|
393
|
+
date_format=None,
|
|
394
|
+
logo_path=None,
|
|
395
|
+
logo_zoom=0.07,
|
|
396
|
+
show_icons=False,
|
|
397
|
+
icon_zoom=0.06,
|
|
398
|
+
)
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
| Parameter | Type | Default | Description |
|
|
402
|
+
|-----------|------|---------|-------------|
|
|
403
|
+
| `data` | `pd.DataFrame` | *(required)* | Input DataFrame with at least the `value_col` column. |
|
|
404
|
+
| `chart_type` | `str` | *(required)* | `"XmR"`, `"p"`, `"u"`, `"c"`, or `"run"` (case-insensitive). |
|
|
405
|
+
| `value_col` | `str` | `"value"` | Column containing the measured values. |
|
|
406
|
+
| `subgroup_col` | `str \| None` | `"subgroup_size"` | Column with subgroup sizes. Required for `"p"` and `"u"`. |
|
|
407
|
+
| `numerator_col` | `str \| None` | `None` | For `"p"` charts: column with event counts when `value_col` holds the denominator. |
|
|
408
|
+
| `x_col` | `str \| None` | `None` | Column for the x-axis. Auto-detects `DatetimeIndex` if `None`. |
|
|
409
|
+
| `title` | `str \| None` | `None` | Chart title. Auto-generated if omitted. |
|
|
410
|
+
| `xlabel` | `str` | `"Observation"` | X-axis label. |
|
|
411
|
+
| `ylabel` | `str` | `"Value"` | Y-axis label. |
|
|
412
|
+
| `improvement_direction` | `str` | `"high"` | `"high"` or `"low"`. Controls point colouring. |
|
|
413
|
+
| `target` | `float \| None` | `None` | Optional target value for the target line and assurance calculation. |
|
|
414
|
+
| `show_target` | `bool` | `False` | Draw a dashed target line at `target`. |
|
|
415
|
+
| `shade_band` | `bool` | `False` | Fill between UCL and LCL with a translucent band. |
|
|
416
|
+
| `shade_color` | `str` | `"#41B6E6"` | Colour for tolerance-band shading. |
|
|
417
|
+
| `nhs_logo_path` | `str \| None` | `None` | Logo inside the axes (legacy). Use `logo_path` instead. |
|
|
418
|
+
| `ax` | `Axes \| None` | `None` | Existing axes to draw on. Creates a new figure when `None`. |
|
|
419
|
+
| `figsize` | `tuple` | `(12, 5)` | Figure size in inches. Ignored when `ax` is provided. |
|
|
420
|
+
| `show_legend` | `bool` | `True` | Add a colour legend. |
|
|
421
|
+
| `change_points` | `list[dict] \| None` | `None` | Vertical annotation lines. Each dict needs `"x"` and `"label"`. |
|
|
422
|
+
| `auto_rebase` | `bool` | `False` | Auto-detect sustained improvement and recalculate limits. |
|
|
423
|
+
| `date_format` | `str \| None` | `None` | `strftime`-style format for datetime x-axis. |
|
|
424
|
+
| `logo_path` | `str \| None` | `None` | Logo image at top-right of figure. |
|
|
425
|
+
| `logo_zoom` | `float` | `0.07` | Logo height as fraction of figure height. |
|
|
426
|
+
| `show_icons` | `bool` | `False` | Display MDC variation & assurance icons. |
|
|
427
|
+
| `icon_zoom` | `float` | `0.06` | Icon height as fraction of figure height. |
|
|
428
|
+
|
|
429
|
+
**Returns:** `(fig, ax)` — `matplotlib.figure.Figure` and `matplotlib.axes.Axes`.
|
|
430
|
+
|
|
431
|
+
---
|
|
432
|
+
|
|
433
|
+
### `plot_run_chart`
|
|
434
|
+
|
|
435
|
+
```python
|
|
436
|
+
fig, ax = plot_run_chart(
|
|
437
|
+
data,
|
|
438
|
+
value_col="value",
|
|
439
|
+
x_col=None,
|
|
440
|
+
title=None,
|
|
441
|
+
xlabel="Observation",
|
|
442
|
+
ylabel="Value",
|
|
443
|
+
improvement_direction="high",
|
|
444
|
+
target=None,
|
|
445
|
+
show_target=False,
|
|
446
|
+
nhs_logo_path=None,
|
|
447
|
+
ax=None,
|
|
448
|
+
figsize=(12, 5),
|
|
449
|
+
show_legend=True,
|
|
450
|
+
change_points=None,
|
|
451
|
+
date_format=None,
|
|
452
|
+
logo_path=None,
|
|
453
|
+
logo_zoom=0.07,
|
|
454
|
+
show_icons=False,
|
|
455
|
+
icon_zoom=0.06,
|
|
456
|
+
)
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
Same parameter semantics as `plot_spc_chart` (without `chart_type`,
|
|
460
|
+
`subgroup_col`, `numerator_col`, `shade_band`, `shade_color`, `auto_rebase`).
|
|
461
|
+
|
|
462
|
+
**Returns:** `(fig, ax)`.
|
|
463
|
+
|
|
464
|
+
---
|
|
465
|
+
|
|
466
|
+
### `calculate_control_limits`
|
|
467
|
+
|
|
468
|
+
Returns the input DataFrame extended with `mean`, `ucl`, `lcl`, `uwl`, `lwl`
|
|
469
|
+
columns (or just `mean` for run charts).
|
|
470
|
+
|
|
471
|
+
### `detect_special_causes`
|
|
472
|
+
|
|
473
|
+
Returns the DataFrame extended with boolean columns `rule1`, `rule2`, `rule3`,
|
|
474
|
+
`rule4`, and `special_cause`.
|
|
475
|
+
|
|
476
|
+
### `detect_run_chart_signals`
|
|
477
|
+
|
|
478
|
+
Returns the DataFrame extended with `run_shift`, `run_trend`, and `run_signal`.
|
|
479
|
+
|
|
480
|
+
### `rebase_control_limits`
|
|
481
|
+
|
|
482
|
+
Returns the DataFrame with limits recalculated per improvement phase and a
|
|
483
|
+
`rebase_phase` integer column.
|
|
484
|
+
|
|
485
|
+
### `show_summary`
|
|
486
|
+
|
|
487
|
+
Generates a programmatic summary dictionary for a chart, including variation
|
|
488
|
+
type, assurance status, descriptive statistics, triggered SPC rules, and a
|
|
489
|
+
list of signal points. Pass `show_summary=True` to `plot_spc_chart` or
|
|
490
|
+
`plot_run_chart` to render the summary as an additional figure.
|
|
491
|
+
|
|
492
|
+
```python
|
|
493
|
+
from abspc import show_summary
|
|
494
|
+
|
|
495
|
+
summary = show_summary(data, chart_type="XmR", improvement_direction="high", target=60)
|
|
496
|
+
print(summary["variation"], summary["assurance"])
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
### `plot_mdc_summary_table`
|
|
500
|
+
|
|
501
|
+
Renders an NHS MDC-style summary table for one or more measures (see the
|
|
502
|
+
[MDC Summary Table](#mdc-summary-table) section above).
|
|
503
|
+
|
|
504
|
+
---
|
|
505
|
+
|
|
506
|
+
## Running Tests
|
|
507
|
+
|
|
508
|
+
```bash
|
|
509
|
+
pip install -e ".[dev]"
|
|
510
|
+
pytest
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
160 unit tests covering all chart types, SPC rules, run-chart signals,
|
|
514
|
+
auto-rebase, change-point annotations, summary generation, and plotting.
|
abspc/__init__.py
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""
|
|
2
|
+
abspc
|
|
3
|
+
=====
|
|
4
|
+
A Python package for Statistical Process Control (SPC) charts following
|
|
5
|
+
the NHS Making Data Count (MDC) methodology.
|
|
6
|
+
|
|
7
|
+
Supported chart types
|
|
8
|
+
---------------------
|
|
9
|
+
* ``"XmR"`` – Individuals / moving-range chart
|
|
10
|
+
* ``"p"`` – Proportion chart
|
|
11
|
+
* ``"u"`` – Counts-per-unit chart
|
|
12
|
+
* ``"c"`` – Counts in a fixed population
|
|
13
|
+
* ``"t"`` – Time between rare events (Nelson transformation)
|
|
14
|
+
* ``"g"`` – Opportunities between rare events (geometric distribution)
|
|
15
|
+
* ``"run"`` – Basic run chart (median centre line, no control limits)
|
|
16
|
+
|
|
17
|
+
Quick start
|
|
18
|
+
-----------
|
|
19
|
+
>>> import pandas as pd
|
|
20
|
+
>>> from abspc import plot_spc_chart, plot_run_chart
|
|
21
|
+
>>> data = pd.DataFrame({"value": [10, 12, 11, 15, 9, 13, 11, 14, 10, 12]})
|
|
22
|
+
>>> plot_spc_chart(data, chart_type="XmR")
|
|
23
|
+
>>> plot_run_chart(data)
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
from .spc import (
|
|
27
|
+
calculate_control_limits,
|
|
28
|
+
detect_special_causes,
|
|
29
|
+
detect_run_chart_signals,
|
|
30
|
+
rebase_control_limits,
|
|
31
|
+
determine_point_colours,
|
|
32
|
+
determine_variation_type,
|
|
33
|
+
determine_assurance_type,
|
|
34
|
+
show_summary,
|
|
35
|
+
SPC_MIN_DATA_POINTS,
|
|
36
|
+
)
|
|
37
|
+
from .plot import plot_spc_chart, plot_run_chart, plot_mdc_summary_table
|
|
38
|
+
from .utils import validate_data, add_logo, add_annotation
|
|
39
|
+
|
|
40
|
+
__all__ = [
|
|
41
|
+
"calculate_control_limits",
|
|
42
|
+
"detect_special_causes",
|
|
43
|
+
"detect_run_chart_signals",
|
|
44
|
+
"rebase_control_limits",
|
|
45
|
+
"determine_point_colours",
|
|
46
|
+
"determine_variation_type",
|
|
47
|
+
"determine_assurance_type",
|
|
48
|
+
"show_summary",
|
|
49
|
+
"plot_spc_chart",
|
|
50
|
+
"plot_run_chart",
|
|
51
|
+
"plot_mdc_summary_table",
|
|
52
|
+
"validate_data",
|
|
53
|
+
"add_logo",
|
|
54
|
+
"add_annotation",
|
|
55
|
+
"SPC_MIN_DATA_POINTS",
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
__version__ = "0.2.1"
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|