priorityx 0.1.2__tar.gz → 0.2.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.
- {priorityx-0.1.2 → priorityx-0.2.0}/Makefile +4 -0
- {priorityx-0.1.2 → priorityx-0.2.0}/PKG-INFO +27 -12
- priorityx-0.2.0/README.md +60 -0
- {priorityx-0.1.2 → priorityx-0.2.0}/docs/api-reference.md +84 -8
- {priorityx-0.1.2 → priorityx-0.2.0}/docs/methodology.md +4 -2
- priorityx-0.2.0/docs/priority_classification.md +41 -0
- {priorityx-0.1.2 → priorityx-0.2.0}/docs/quickstart.md +22 -7
- priorityx-0.2.0/examples/README.md +36 -0
- priorityx-0.2.0/examples/bugs/bugs_monitoring.py +41 -0
- priorityx-0.2.0/examples/incidents/incident_monitoring.py +151 -0
- priorityx-0.2.0/examples/violations/violations_monitoring.py +128 -0
- {priorityx-0.1.2 → priorityx-0.2.0}/pyproject.toml +5 -5
- {priorityx-0.1.2 → priorityx-0.2.0}/scripts/version.py +5 -12
- {priorityx-0.1.2 → priorityx-0.2.0}/src/priorityx/__init__.py +1 -1
- {priorityx-0.1.2 → priorityx-0.2.0}/src/priorityx/core/filters.py +55 -60
- {priorityx-0.1.2 → priorityx-0.2.0}/src/priorityx/core/glmm.py +146 -129
- {priorityx-0.1.2 → priorityx-0.2.0}/src/priorityx/core/quadrants.py +4 -5
- {priorityx-0.1.2 → priorityx-0.2.0}/src/priorityx/tracking/drivers.py +148 -83
- {priorityx-0.1.2 → priorityx-0.2.0}/src/priorityx/tracking/movement.py +47 -56
- {priorityx-0.1.2 → priorityx-0.2.0}/src/priorityx/tracking/transitions.py +90 -5
- {priorityx-0.1.2 → priorityx-0.2.0}/src/priorityx/utils/helpers.py +99 -25
- {priorityx-0.1.2 → priorityx-0.2.0}/src/priorityx/viz/matrix.py +52 -28
- {priorityx-0.1.2 → priorityx-0.2.0}/src/priorityx/viz/timeline.py +129 -33
- priorityx-0.2.0/src/priorityx/viz/trajectory.py +289 -0
- {priorityx-0.1.2 → priorityx-0.2.0}/tests/test_drivers.py +41 -27
- {priorityx-0.1.2 → priorityx-0.2.0}/tests/test_glmm.py +48 -24
- {priorityx-0.1.2 → priorityx-0.2.0}/tests/test_quadrants.py +9 -1
- {priorityx-0.1.2 → priorityx-0.2.0}/tests/test_transitions.py +20 -16
- {priorityx-0.1.2 → priorityx-0.2.0}/uv.lock +88 -1282
- priorityx-0.1.2/README.md +0 -43
- priorityx-0.1.2/src/priorityx/viz/trajectory.py +0 -231
- {priorityx-0.1.2 → priorityx-0.2.0}/.github/workflows/release.yml +0 -0
- {priorityx-0.1.2 → priorityx-0.2.0}/.github/workflows/test.yml +0 -0
- {priorityx-0.1.2 → priorityx-0.2.0}/.gitignore +0 -0
- {priorityx-0.1.2 → priorityx-0.2.0}/LICENSE +0 -0
- {priorityx-0.1.2 → priorityx-0.2.0}/src/priorityx/core/__init__.py +0 -0
- {priorityx-0.1.2 → priorityx-0.2.0}/src/priorityx/drivers/__init__.py +0 -0
- {priorityx-0.1.2 → priorityx-0.2.0}/src/priorityx/tracking/__init__.py +0 -0
- {priorityx-0.1.2 → priorityx-0.2.0}/src/priorityx/utils/__init__.py +0 -0
- {priorityx-0.1.2 → priorityx-0.2.0}/src/priorityx/viz/__init__.py +0 -0
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
# Version management for priorityx
|
|
2
|
+
# Semantic versioning: MAJOR.MINOR.PATCH
|
|
3
|
+
# - patch: bug fixes (0.1.1 -> 0.1.2)
|
|
4
|
+
# - minor: new features, backward compatible (0.1.2 -> 0.2.0)
|
|
5
|
+
# - major: breaking changes (0.2.0 -> 1.0.0)
|
|
2
6
|
|
|
3
7
|
.PHONY: release release-patch release-minor release-major test
|
|
4
8
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: priorityx
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Entity prioritization and escalation detection using GLMM statistical models
|
|
5
5
|
Project-URL: Homepage, https://github.com/okkymabruri/priorityx
|
|
6
6
|
Project-URL: Repository, https://github.com/okkymabruri/priorityx
|
|
@@ -9,7 +9,7 @@ Author-email: Okky Mabruri <okkymbrur@gmail.com>
|
|
|
9
9
|
License: MIT
|
|
10
10
|
License-File: LICENSE
|
|
11
11
|
Keywords: escalation-detection,glmm,prioritization,risk-analysis,statistical-modeling
|
|
12
|
-
Classifier: Development Status ::
|
|
12
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
13
13
|
Classifier: Intended Audience :: Developers
|
|
14
14
|
Classifier: Intended Audience :: Science/Research
|
|
15
15
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -19,17 +19,23 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.12
|
|
20
20
|
Classifier: Topic :: Scientific/Engineering
|
|
21
21
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
-
Requires-Python: >=3.
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
23
|
Requires-Dist: adjusttext>=1.3.0
|
|
24
24
|
Requires-Dist: matplotlib>=3.9.4
|
|
25
25
|
Requires-Dist: pandas>=2.3.3
|
|
26
|
-
Requires-Dist: polars>=1.35.1
|
|
27
|
-
Requires-Dist: pyarrow>=21.0.0
|
|
28
26
|
Requires-Dist: statsmodels>=0.14.5
|
|
29
27
|
Description-Content-Type: text/markdown
|
|
30
28
|
|
|
31
29
|
# Priorityx: Entity prioritization and escalation detection using GLMM statistical models
|
|
32
30
|
|
|
31
|
+
[](https://badge.fury.io/py/priorityx)
|
|
32
|
+
[](https://pepy.tech/project/priorityx)
|
|
33
|
+
[](https://github.com/okkymabruri/priorityx/actions)
|
|
34
|
+
[](https://www.python.org/downloads/)
|
|
35
|
+
[](https://opensource.org/licenses/MIT)
|
|
36
|
+
|
|
37
|
+
Entity prioritization and escalation detection using GLMM statistical models
|
|
38
|
+
|
|
33
39
|
## Installation
|
|
34
40
|
|
|
35
41
|
```bash
|
|
@@ -38,12 +44,20 @@ pip install priorityx
|
|
|
38
44
|
|
|
39
45
|
## Quick Start
|
|
40
46
|
|
|
47
|
+
### Deterministic runs
|
|
48
|
+
|
|
49
|
+
Set `PRIORITYX_GLMM_SEED` (or call `set_glmm_random_seed()`) before running analyses to obtain repeatable GLMM estimates during debugging or CI checks:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
PRIORITYX_GLMM_SEED=1234 python tmp/complaints_analysis.py
|
|
53
|
+
```
|
|
54
|
+
|
|
41
55
|
```python
|
|
42
|
-
import
|
|
56
|
+
import pandas as pd
|
|
43
57
|
from priorityx.core.glmm import fit_priority_matrix
|
|
44
58
|
from priorityx.viz.matrix import plot_priority_matrix
|
|
45
59
|
|
|
46
|
-
df =
|
|
60
|
+
df = pd.read_csv("data.csv")
|
|
47
61
|
|
|
48
62
|
results, stats = fit_priority_matrix(
|
|
49
63
|
df,
|
|
@@ -57,10 +71,10 @@ plot_priority_matrix(results, entity_name="Service", save_plot=True)
|
|
|
57
71
|
|
|
58
72
|
## Features
|
|
59
73
|
|
|
60
|
-
- GLMM-based priority
|
|
61
|
-
-
|
|
62
|
-
-
|
|
63
|
-
-
|
|
74
|
+
- GLMM-based priority matrix (Q1–Q4) with entity-level intercept/slope insights
|
|
75
|
+
- Priority-based transition timeline (Crisis / Investigate / Monitor / Low) with spike markers (`*X`, `*Y`, `*XY`)
|
|
76
|
+
- Cumulative movement tracking and trajectory visualizations
|
|
77
|
+
- Deterministic seeding option for reproducible GLMM runs (set `PRIORITYX_GLMM_SEED`)
|
|
64
78
|
|
|
65
79
|
## Use Cases
|
|
66
80
|
|
|
@@ -70,4 +84,5 @@ IT incidents, software bugs, compliance violations, performance monitoring.
|
|
|
70
84
|
|
|
71
85
|
- [Quick Start](docs/quickstart.md)
|
|
72
86
|
- [API Reference](docs/api-reference.md)
|
|
73
|
-
- [Methodology](docs/methodology.md)
|
|
87
|
+
- [Methodology](docs/methodology.md)
|
|
88
|
+
- [Priority Classification](docs/priority_classification.md)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Priorityx: Entity prioritization and escalation detection using GLMM statistical models
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/py/priorityx)
|
|
4
|
+
[](https://pepy.tech/project/priorityx)
|
|
5
|
+
[](https://github.com/okkymabruri/priorityx/actions)
|
|
6
|
+
[](https://www.python.org/downloads/)
|
|
7
|
+
[](https://opensource.org/licenses/MIT)
|
|
8
|
+
|
|
9
|
+
Entity prioritization and escalation detection using GLMM statistical models
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install priorityx
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
### Deterministic runs
|
|
20
|
+
|
|
21
|
+
Set `PRIORITYX_GLMM_SEED` (or call `set_glmm_random_seed()`) before running analyses to obtain repeatable GLMM estimates during debugging or CI checks:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
PRIORITYX_GLMM_SEED=1234 python tmp/complaints_analysis.py
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
import pandas as pd
|
|
29
|
+
from priorityx.core.glmm import fit_priority_matrix
|
|
30
|
+
from priorityx.viz.matrix import plot_priority_matrix
|
|
31
|
+
|
|
32
|
+
df = pd.read_csv("data.csv")
|
|
33
|
+
|
|
34
|
+
results, stats = fit_priority_matrix(
|
|
35
|
+
df,
|
|
36
|
+
entity_col="service",
|
|
37
|
+
timestamp_col="date",
|
|
38
|
+
temporal_granularity="quarterly"
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
plot_priority_matrix(results, entity_name="Service", save_plot=True)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Features
|
|
45
|
+
|
|
46
|
+
- GLMM-based priority matrix (Q1–Q4) with entity-level intercept/slope insights
|
|
47
|
+
- Priority-based transition timeline (Crisis / Investigate / Monitor / Low) with spike markers (`*X`, `*Y`, `*XY`)
|
|
48
|
+
- Cumulative movement tracking and trajectory visualizations
|
|
49
|
+
- Deterministic seeding option for reproducible GLMM runs (set `PRIORITYX_GLMM_SEED`)
|
|
50
|
+
|
|
51
|
+
## Use Cases
|
|
52
|
+
|
|
53
|
+
IT incidents, software bugs, compliance violations, performance monitoring.
|
|
54
|
+
|
|
55
|
+
## Documentation
|
|
56
|
+
|
|
57
|
+
- [Quick Start](docs/quickstart.md)
|
|
58
|
+
- [API Reference](docs/api-reference.md)
|
|
59
|
+
- [Methodology](docs/methodology.md)
|
|
60
|
+
- [Priority Classification](docs/priority_classification.md)
|
|
@@ -25,7 +25,7 @@ results, stats = fit_priority_matrix(
|
|
|
25
25
|
Fits Poisson GLMM to classify entities into priority quadrants.
|
|
26
26
|
|
|
27
27
|
**Parameters:**
|
|
28
|
-
- `df`:
|
|
28
|
+
- `df`: pandas DataFrame
|
|
29
29
|
- `entity_col`: Entity identifier column name
|
|
30
30
|
- `timestamp_col`: Date column name
|
|
31
31
|
- `count_col`: Count metric column (optional, defaults to row count)
|
|
@@ -41,6 +41,8 @@ Fits Poisson GLMM to classify entities into priority quadrants.
|
|
|
41
41
|
- `results`: DataFrame with entity, Random_Intercept, Random_Slope, count, quadrant
|
|
42
42
|
- `stats`: Dictionary with model statistics
|
|
43
43
|
|
|
44
|
+
> **Reproducibility:** set the environment variable `PRIORITYX_GLMM_SEED` or call `set_glmm_random_seed(value)` before invoking `fit_priority_matrix` to obtain deterministic variational Bayes estimates.
|
|
45
|
+
|
|
44
46
|
---
|
|
45
47
|
|
|
46
48
|
## Tracking Functions
|
|
@@ -85,6 +87,60 @@ Extracts quadrant transitions from movement data.
|
|
|
85
87
|
**Returns:**
|
|
86
88
|
- DataFrame with transition details and risk levels
|
|
87
89
|
|
|
90
|
+
### extract_transition_drivers
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
from priorityx.tracking.drivers import extract_transition_drivers
|
|
94
|
+
|
|
95
|
+
analysis = extract_transition_drivers(
|
|
96
|
+
movement_df,
|
|
97
|
+
df_raw,
|
|
98
|
+
entity_name="Service A",
|
|
99
|
+
quarter_from="2024-Q2",
|
|
100
|
+
quarter_to="2024-Q3",
|
|
101
|
+
entity_col="service",
|
|
102
|
+
timestamp_col="date",
|
|
103
|
+
subcategory_cols=["type", "category"], # Optional
|
|
104
|
+
text_col="description" # Optional
|
|
105
|
+
)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Analyzes root causes of a quadrant transition.
|
|
109
|
+
|
|
110
|
+
**Parameters:**
|
|
111
|
+
- `movement_df`: Output from track_cumulative_movement()
|
|
112
|
+
- `df_raw`: Raw event data (pandas DataFrame)
|
|
113
|
+
- `entity_name`: Entity to analyze
|
|
114
|
+
- `quarter_from`: Starting quarter (e.g., "2024-Q2")
|
|
115
|
+
- `quarter_to`: Ending quarter (e.g., "2024-Q3")
|
|
116
|
+
- `entity_col`: Entity column name
|
|
117
|
+
- `timestamp_col`: Timestamp column name
|
|
118
|
+
- `subcategory_cols`: Optional list of subcategory columns
|
|
119
|
+
- `text_col`: Optional text column for keyword analysis
|
|
120
|
+
|
|
121
|
+
**Returns:**
|
|
122
|
+
- Dictionary with transition overview, magnitude metrics, subcategory drivers, keyword drivers, and priority classification
|
|
123
|
+
|
|
124
|
+
### classify_priority
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
from priorityx.tracking.drivers import classify_priority
|
|
128
|
+
|
|
129
|
+
priority, reason, spike_axis = classify_priority(
|
|
130
|
+
from_quadrant="Q3",
|
|
131
|
+
to_quadrant="Q1",
|
|
132
|
+
x=0.5, y=0.6,
|
|
133
|
+
x_delta=0.5, y_delta=0.5,
|
|
134
|
+
count_delta=100,
|
|
135
|
+
percent_change=200
|
|
136
|
+
)
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Classifies supervisory priority (1=Critical, 2=Investigate, 3=Monitor, 4=Low).
|
|
140
|
+
|
|
141
|
+
**Returns:**
|
|
142
|
+
- Tuple of (priority, reason, spike_axis)
|
|
143
|
+
|
|
88
144
|
---
|
|
89
145
|
|
|
90
146
|
## Visualization Functions
|
|
@@ -118,18 +174,19 @@ fig = plot_transition_timeline(
|
|
|
118
174
|
filter_risk_levels=["critical", "high"],
|
|
119
175
|
max_entities=20,
|
|
120
176
|
save_plot=False,
|
|
121
|
-
output_dir="plot"
|
|
177
|
+
output_dir="plot",
|
|
178
|
+
movement_df=movement_df
|
|
122
179
|
)
|
|
123
180
|
```
|
|
124
181
|
|
|
125
|
-
Creates timeline heatmap of transitions.
|
|
182
|
+
Creates timeline heatmap of transitions. Passing `movement_df` is required to compute the Crisis/Investigate/Monitor/Low priority tiers and spike markers (`*X`, `*Y`, `*XY`). Omitting it falls back to legacy risk-level tags.
|
|
126
183
|
|
|
127
|
-
###
|
|
184
|
+
### plot_entity_trajectories
|
|
128
185
|
|
|
129
186
|
```python
|
|
130
|
-
from priorityx.viz.trajectory import
|
|
187
|
+
from priorityx.viz.trajectory import plot_entity_trajectories
|
|
131
188
|
|
|
132
|
-
fig =
|
|
189
|
+
fig = plot_entity_trajectories(
|
|
133
190
|
movement_df,
|
|
134
191
|
entity_name="Entity",
|
|
135
192
|
max_entities=10,
|
|
@@ -138,7 +195,7 @@ fig = plot_movement_trajectories(
|
|
|
138
195
|
)
|
|
139
196
|
```
|
|
140
197
|
|
|
141
|
-
Creates trajectory plot showing
|
|
198
|
+
Creates trajectory plot showing entity paths through priority space.
|
|
142
199
|
|
|
143
200
|
---
|
|
144
201
|
|
|
@@ -147,10 +204,29 @@ Creates trajectory plot showing movement through priority space.
|
|
|
147
204
|
### Display Summaries
|
|
148
205
|
|
|
149
206
|
```python
|
|
150
|
-
from priorityx.utils.helpers import
|
|
207
|
+
from priorityx.utils.helpers import (
|
|
208
|
+
display_quadrant_summary,
|
|
209
|
+
display_transition_summary,
|
|
210
|
+
display_movement_summary
|
|
211
|
+
)
|
|
151
212
|
|
|
152
213
|
display_quadrant_summary(results_df, entity_name="Service")
|
|
153
214
|
display_transition_summary(transitions_df, entity_name="Service")
|
|
215
|
+
display_movement_summary(movement_df, entity_name="Service")
|
|
154
216
|
```
|
|
155
217
|
|
|
156
218
|
Prints formatted summaries of analysis results.
|
|
219
|
+
|
|
220
|
+
### display_transition_drivers
|
|
221
|
+
|
|
222
|
+
```python
|
|
223
|
+
from priorityx.tracking.drivers import display_transition_drivers
|
|
224
|
+
|
|
225
|
+
display_transition_drivers(analysis, show_keywords=True)
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Prints transition driver analysis in human-readable format.
|
|
229
|
+
|
|
230
|
+
**Parameters:**
|
|
231
|
+
- `analysis`: Output from extract_transition_drivers()
|
|
232
|
+
- `show_keywords`: Whether to show keyword analysis (default: False)
|
|
@@ -29,7 +29,7 @@ count ~ time + seasonal_effects + (1 + time | entity)
|
|
|
29
29
|
|
|
30
30
|
Entities classified based on random effects:
|
|
31
31
|
|
|
32
|
-
**Q1 (
|
|
32
|
+
**Q1 (Critical):** intercept > 0, slope > 0, count ≥ 50
|
|
33
33
|
- High volume, accelerating growth
|
|
34
34
|
- Requires immediate attention
|
|
35
35
|
|
|
@@ -45,7 +45,9 @@ Entities classified based on random effects:
|
|
|
45
45
|
- High volume but not accelerating
|
|
46
46
|
- Persistent baseline issues
|
|
47
47
|
|
|
48
|
-
The count threshold for Q1 prevents low-volume entities from being mislabeled as
|
|
48
|
+
The count threshold for Q1 prevents low-volume entities from being mislabeled as Critical.
|
|
49
|
+
|
|
50
|
+
Priority tiers applied in the transition timeline build on these quadrants with velocity-based rules (see `docs/priority_classification.md`) to differentiate Crisis, Investigate, Monitor, and Low responses.
|
|
49
51
|
|
|
50
52
|
## Movement Tracking
|
|
51
53
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Priority Classification Overview
|
|
2
|
+
|
|
3
|
+
A four-tier priority system ranks quadrant transitions by urgency using movement velocity, magnitude, and spike detection. Priorities are computed inside `plot_transition_timeline(..., movement_df=...)` and saved in transition CSVs.
|
|
4
|
+
|
|
5
|
+
## Priority Tiers
|
|
6
|
+
|
|
7
|
+
| Priority | Label & Color | Main Triggers | Recommended Action |
|
|
8
|
+
|----------|---------------|---------------|--------------------|
|
|
9
|
+
| **1 – Crisis** 🔴 | Explosion requiring immediate response | ΔX ≥ 0.40 or ΔY ≥ 0.40 (≈3σ); volume jump ≥ 50 with ≥500 % growth; both axes spiking (`*XY`) | Launch crisis playbook, staff war room, monitor daily |
|
|
10
|
+
| **2 – Investigate** 🟠 | Rapid escalation needing urgent review | |ΔX > 0.15 or |ΔY > 0.15; entry into Q1 with strong position; ≥100 % growth with ≥5 new complaints | Trigger early warning, assign analysts, tighten monitoring cadence |
|
|
11
|
+
| **3 – Monitor** 🟡 | Borderline movement worth watching | Position within ±0.10 of quadrant boundary; gentle Q1 entry | Track trend, document findings, review quarterly |
|
|
12
|
+
| **4 – Low** 🟢 | Stable or improving | No conditions above met | Maintain routine oversight |
|
|
13
|
+
|
|
14
|
+
## Spike Indicators
|
|
15
|
+
|
|
16
|
+
| Marker | Meaning | Threshold |
|
|
17
|
+
|--------|---------|-----------|
|
|
18
|
+
| `*Y` | Growth spike | ΔY ≥ 0.40 |
|
|
19
|
+
| `*X` | Volume spike | ΔX ≥ 0.40 |
|
|
20
|
+
| `*XY` | Simultaneous spikes | ΔX ≥ 0.40 **and** ΔY ≥ 0.40 |
|
|
21
|
+
|
|
22
|
+
## Threshold Reference
|
|
23
|
+
|
|
24
|
+
| Metric | Cut-off | Notes |
|
|
25
|
+
|--------|---------|-------|
|
|
26
|
+
| Crisis spike | ±0.40 | ≈2.74σ, highlights extreme moves |
|
|
27
|
+
| Velocity trigger | ±0.15 | Sustained acceleration worth investigation |
|
|
28
|
+
| Growth shock | ≥100 % **and** ≥5 complaints | Filters out noise from tiny bases |
|
|
29
|
+
| Explosion | ≥500 % **and** ≥50 complaints | High-volume surges escalated to Crisis |
|
|
30
|
+
| Borderline band | ±0.10 | Used for Monitor prioritization |
|
|
31
|
+
|
|
32
|
+
## Usage Guidelines
|
|
33
|
+
|
|
34
|
+
1. **Always supply movement data**: `plot_transition_timeline(transitions, movement_df=movement)` is required for priority scoring; omitting it defaults to Priority 2.
|
|
35
|
+
2. **Filter by priority**: e.g. `transitions[transitions["priority"] == 1]` to summarize crises; risk_level is retained for backward compatibility only.
|
|
36
|
+
3. **Inspect spike markers**: `*X`, `*Y`, `*XY` signal urgent within-quadrant acceleration that may precede cross-quadrant jumps.
|
|
37
|
+
4. **Adjust tracking range deliberately**: longer histories surface more transitions; short windows emphasize recent moves.
|
|
38
|
+
|
|
39
|
+
## Changelog
|
|
40
|
+
|
|
41
|
+
- **2024-11-09** – Introduced priority classification, spike markers, and timeline integration.
|
|
@@ -9,12 +9,13 @@ pip install priorityx
|
|
|
9
9
|
## Basic Usage
|
|
10
10
|
|
|
11
11
|
```python
|
|
12
|
-
import
|
|
12
|
+
import pandas as pd
|
|
13
13
|
from priorityx.core.glmm import fit_priority_matrix
|
|
14
14
|
from priorityx.viz.matrix import plot_priority_matrix
|
|
15
15
|
|
|
16
16
|
# load your data
|
|
17
|
-
df =
|
|
17
|
+
df = pd.read_csv("your_data.csv")
|
|
18
|
+
df["date"] = pd.to_datetime(df["date"])
|
|
18
19
|
|
|
19
20
|
# fit priority matrix
|
|
20
21
|
results, stats = fit_priority_matrix(
|
|
@@ -34,6 +35,7 @@ plot_priority_matrix(results, entity_name="Service", save_plot=True)
|
|
|
34
35
|
```python
|
|
35
36
|
from priorityx.tracking.movement import track_cumulative_movement
|
|
36
37
|
from priorityx.tracking.transitions import extract_transitions
|
|
38
|
+
from priorityx.tracking.drivers import extract_transition_drivers, display_transition_drivers
|
|
37
39
|
from priorityx.viz.timeline import plot_transition_timeline
|
|
38
40
|
|
|
39
41
|
# track movement over time
|
|
@@ -49,6 +51,20 @@ transitions = extract_transitions(movement)
|
|
|
49
51
|
|
|
50
52
|
# visualize transitions
|
|
51
53
|
plot_transition_timeline(transitions, entity_name="Service", save_plot=True)
|
|
54
|
+
|
|
55
|
+
# analyze drivers for specific transition
|
|
56
|
+
if not transitions.empty:
|
|
57
|
+
first_transition = transitions.iloc[0]
|
|
58
|
+
analysis = extract_transition_drivers(
|
|
59
|
+
movement_df=movement,
|
|
60
|
+
df_raw=df,
|
|
61
|
+
entity_name=first_transition["entity"],
|
|
62
|
+
quarter_from=first_transition["from_quarter"],
|
|
63
|
+
quarter_to=first_transition["transition_quarter"],
|
|
64
|
+
entity_col="service",
|
|
65
|
+
timestamp_col="date"
|
|
66
|
+
)
|
|
67
|
+
display_transition_drivers(analysis)
|
|
52
68
|
```
|
|
53
69
|
|
|
54
70
|
## Data Requirements
|
|
@@ -60,9 +76,8 @@ Your data needs:
|
|
|
60
76
|
|
|
61
77
|
## Output
|
|
62
78
|
|
|
63
|
-
|
|
64
|
-
-
|
|
65
|
-
-
|
|
66
|
-
- Movement: CSV + trajectory plot
|
|
79
|
+
By default, outputs saved to:
|
|
80
|
+
- **`plot/`** - All PNG visualizations (priority matrix, transitions, trajectories)
|
|
81
|
+
- **`results/`** - All CSV data files (entity scores, transitions, movement tracking)
|
|
67
82
|
|
|
68
|
-
|
|
83
|
+
You can customize output directories using the `output_dir` parameter in visualization functions.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Examples
|
|
2
|
+
|
|
3
|
+
These examples demonstrate priorityx usage with different datasets.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
Install priorityx from PyPI:
|
|
8
|
+
```bash
|
|
9
|
+
pip install priorityx
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Or install latest from source:
|
|
13
|
+
```bash
|
|
14
|
+
pip install git+https://github.com/okkymabruri/priorityx.git
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Running Examples
|
|
18
|
+
|
|
19
|
+
**IT Incidents** (1,621 incidents, 10 services)
|
|
20
|
+
```bash
|
|
21
|
+
python examples/incidents/incident_monitoring.py
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**Compliance Violations** (495 violations, 10 departments)
|
|
25
|
+
```bash
|
|
26
|
+
python examples/violations/violations_monitoring.py
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Software Bugs** (576 bugs, 10 components)
|
|
30
|
+
Pre-generated CSV only. Use as input for your own analysis.
|
|
31
|
+
|
|
32
|
+
## Output
|
|
33
|
+
|
|
34
|
+
Results saved to:
|
|
35
|
+
- `plot/` - Visualizations (PNG files)
|
|
36
|
+
- `results/` - Data tables (CSV files)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# software bug tracking example
|
|
2
|
+
|
|
3
|
+
import pandas as pd
|
|
4
|
+
|
|
5
|
+
from priorityx.core.glmm import fit_priority_matrix
|
|
6
|
+
from priorityx.viz.matrix import plot_priority_matrix
|
|
7
|
+
|
|
8
|
+
# load bug reports
|
|
9
|
+
df = pd.read_csv("examples/bugs/bugs.csv")
|
|
10
|
+
|
|
11
|
+
# parse date column
|
|
12
|
+
df["date"] = pd.to_datetime(df["reported_date"])
|
|
13
|
+
|
|
14
|
+
# fit priority matrix
|
|
15
|
+
temporal_granularity = "quarterly"
|
|
16
|
+
entity_name = "Component"
|
|
17
|
+
results, stats = fit_priority_matrix(
|
|
18
|
+
df,
|
|
19
|
+
entity_col="component",
|
|
20
|
+
timestamp_col="date",
|
|
21
|
+
temporal_granularity=temporal_granularity,
|
|
22
|
+
min_observations=4,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
# display results
|
|
26
|
+
print("Software Bug Priority Matrix:")
|
|
27
|
+
print(results[["entity", "Random_Intercept", "Random_Slope", "count", "quadrant"]])
|
|
28
|
+
|
|
29
|
+
# visualize
|
|
30
|
+
plot_priority_matrix(
|
|
31
|
+
results,
|
|
32
|
+
entity_name=entity_name,
|
|
33
|
+
show_quadrant_labels=True,
|
|
34
|
+
save_plot=True,
|
|
35
|
+
save_csv=True,
|
|
36
|
+
output_dir="examples/bugs/plot",
|
|
37
|
+
)
|
|
38
|
+
print()
|
|
39
|
+
print("Outputs saved to examples/bugs/plot/ and examples/bugs/results/")
|
|
40
|
+
|
|
41
|
+
# %%
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# it incident monitoring example
|
|
2
|
+
|
|
3
|
+
import pandas as pd
|
|
4
|
+
|
|
5
|
+
from priorityx.core.glmm import fit_priority_matrix
|
|
6
|
+
from priorityx.tracking.movement import track_cumulative_movement
|
|
7
|
+
from priorityx.tracking.transitions import extract_transitions
|
|
8
|
+
from priorityx.tracking.drivers import (
|
|
9
|
+
extract_transition_drivers,
|
|
10
|
+
display_transition_drivers,
|
|
11
|
+
)
|
|
12
|
+
from priorityx.viz.matrix import plot_priority_matrix
|
|
13
|
+
from priorityx.viz.timeline import plot_transition_timeline
|
|
14
|
+
from priorityx.viz.trajectory import plot_entity_trajectories
|
|
15
|
+
from priorityx.utils.helpers import (
|
|
16
|
+
display_quadrant_summary,
|
|
17
|
+
display_transition_summary,
|
|
18
|
+
save_dataframe_to_csv,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
# load data
|
|
22
|
+
df = pd.read_csv("examples/incidents/incidents.csv")
|
|
23
|
+
df["date"] = pd.to_datetime(df["date"])
|
|
24
|
+
|
|
25
|
+
print(f"Loaded {len(df)} incidents for {df['service'].nunique()} services")
|
|
26
|
+
print(f"Date range: {df['date'].min()} to {df['date'].max()}")
|
|
27
|
+
|
|
28
|
+
# fit priority matrix
|
|
29
|
+
print()
|
|
30
|
+
print("PRIORITY MATRIX ANALYSIS")
|
|
31
|
+
|
|
32
|
+
temporal_granularity = "quarterly"
|
|
33
|
+
entity_name = "Service"
|
|
34
|
+
results, stats = fit_priority_matrix(
|
|
35
|
+
df,
|
|
36
|
+
entity_col="service",
|
|
37
|
+
timestamp_col="date",
|
|
38
|
+
temporal_granularity=temporal_granularity,
|
|
39
|
+
min_observations=8,
|
|
40
|
+
min_total_count=20,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
print(f"\nAnalyzed {len(results)} services")
|
|
44
|
+
print(results[["entity", "Random_Intercept", "Random_Slope", "count", "quadrant"]])
|
|
45
|
+
|
|
46
|
+
display_quadrant_summary(results, entity_name=entity_name, min_count=0)
|
|
47
|
+
|
|
48
|
+
# visualize
|
|
49
|
+
plot_priority_matrix(
|
|
50
|
+
results,
|
|
51
|
+
entity_name=entity_name,
|
|
52
|
+
show_quadrant_labels=True,
|
|
53
|
+
save_plot=True,
|
|
54
|
+
save_csv=True,
|
|
55
|
+
output_dir="examples/incidents/plot",
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
# track movement
|
|
59
|
+
print()
|
|
60
|
+
print("CUMULATIVE MOVEMENT TRACKING")
|
|
61
|
+
|
|
62
|
+
movement, meta = track_cumulative_movement(
|
|
63
|
+
df,
|
|
64
|
+
entity_col="service",
|
|
65
|
+
timestamp_col="date",
|
|
66
|
+
quarters=["2022-01-01", "2025-01-01"],
|
|
67
|
+
min_total_count=20,
|
|
68
|
+
temporal_granularity=temporal_granularity,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
print(
|
|
72
|
+
f"\nTracked {meta['entities_tracked']} services over {meta['quarters_analyzed']} quarters"
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
# save movement
|
|
76
|
+
movement_path = save_dataframe_to_csv(
|
|
77
|
+
movement,
|
|
78
|
+
artifact="trajectories",
|
|
79
|
+
entity_name=entity_name,
|
|
80
|
+
temporal_granularity=temporal_granularity,
|
|
81
|
+
output_dir="examples/incidents/results",
|
|
82
|
+
)
|
|
83
|
+
print(f"Movement CSV saved: {movement_path}")
|
|
84
|
+
|
|
85
|
+
# visualize entity trajectories
|
|
86
|
+
plot_entity_trajectories(
|
|
87
|
+
movement,
|
|
88
|
+
entity_name=entity_name,
|
|
89
|
+
max_entities=5,
|
|
90
|
+
save_plot=True,
|
|
91
|
+
save_csv=True,
|
|
92
|
+
output_dir="examples/incidents/plot",
|
|
93
|
+
results_dir="examples/incidents/results",
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
# detect transitions
|
|
97
|
+
transitions = extract_transitions(movement, focus_risk_increasing=True)
|
|
98
|
+
|
|
99
|
+
print(f"\nDetected {len(transitions)} risk-increasing transitions")
|
|
100
|
+
display_transition_summary(transitions, entity_name=entity_name)
|
|
101
|
+
|
|
102
|
+
plot_transition_timeline(
|
|
103
|
+
transitions,
|
|
104
|
+
entity_name=entity_name,
|
|
105
|
+
save_plot=True,
|
|
106
|
+
save_csv=True,
|
|
107
|
+
output_dir="examples/incidents/plot",
|
|
108
|
+
movement_df=movement,
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
critical_transitions = transitions[transitions["risk_level"] == "critical"]
|
|
112
|
+
if len(critical_transitions) > 0:
|
|
113
|
+
trans = critical_transitions.iloc[0]
|
|
114
|
+
|
|
115
|
+
print()
|
|
116
|
+
print("DRIVER ANALYSIS EXAMPLE")
|
|
117
|
+
print(f"Analyzing: {trans['entity']}")
|
|
118
|
+
print(f"Transition: {trans['from_quadrant']} -> {trans['to_quadrant']}")
|
|
119
|
+
print(f"Quarter: {trans['transition_quarter']}")
|
|
120
|
+
|
|
121
|
+
entity_movement = (
|
|
122
|
+
movement[movement["entity"] == trans["entity"]]
|
|
123
|
+
.sort_values("quarter")
|
|
124
|
+
.reset_index(drop=True)
|
|
125
|
+
)
|
|
126
|
+
trans_idx = entity_movement[
|
|
127
|
+
entity_movement["quarter"] == trans["transition_quarter"]
|
|
128
|
+
].index[0]
|
|
129
|
+
prev_quarter = (
|
|
130
|
+
entity_movement.loc[trans_idx - 1, "quarter"] if trans_idx > 0 else None
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
if prev_quarter:
|
|
134
|
+
driver_analysis = extract_transition_drivers(
|
|
135
|
+
movement_df=movement,
|
|
136
|
+
df_raw=df,
|
|
137
|
+
entity_name=trans["entity"],
|
|
138
|
+
quarter_from=prev_quarter,
|
|
139
|
+
quarter_to=trans["transition_quarter"],
|
|
140
|
+
entity_col="service",
|
|
141
|
+
timestamp_col="date",
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
display_transition_drivers(driver_analysis)
|
|
145
|
+
|
|
146
|
+
print()
|
|
147
|
+
print(
|
|
148
|
+
"Analysis complete. Check examples/incidents/plot/ and examples/incidents/results/"
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
# %%
|