Incident Records Analyzer
This example applies the ideas from Records and iteration to a small incident report dataset. You use filter, map, list comprehensions, a group_by helper, and reduce / sum / max as needed. Stdlib only; keep the original incidents list unchanged except where you assign query results to new variables.
Create a file incident_records_analyzer.py and run python incident_records_analyzer.py after each step.
Scenario
Section titled “Scenario”You are analyzing incident rows for a maps-style platform. Each row is a dict with id, service, severity, region, duration_min, and resolved.
Sample data
Section titled “Sample data”Paste this at the top of your script (all steps assume it exists):
INCIDENTS = [ {"id": "INC-001", "service": "maps-tile-server", "severity": "P1", "region": "us-east", "duration_min": 45, "resolved": True}, {"id": "INC-002", "service": "auth-service", "severity": "P2", "region": "us-west", "duration_min": 20, "resolved": True}, {"id": "INC-003", "service": "geocoder", "severity": "P1", "region": "eu-west", "duration_min": 90, "resolved": False}, {"id": "INC-004", "service": "routing-engine", "severity": "P3", "region": "us-east", "duration_min": 10, "resolved": True}, {"id": "INC-005", "service": "maps-tile-server", "severity": "P2", "region": "eu-west", "duration_min": 30, "resolved": True}, {"id": "INC-006", "service": "search-index", "severity": "P1", "region": "us-west", "duration_min": 60, "resolved": False}, {"id": "INC-007", "service": "auth-service", "severity": "P3", "region": "us-east", "duration_min": 5, "resolved": True}, {"id": "INC-008", "service": "geocoder", "severity": "P2", "region": "us-west", "duration_min": 25, "resolved": True},]Your tasks
Section titled “Your tasks”- Filter — All rows that are not resolved and have severity P1.
- Map / transform — Build a new list where every row includes
sla_breached:Trueifduration_min > 30, elseFalse. Do not mutate dicts insideINCIDENTS. - Group — Group by
severity. For each severity, print the list of incident ids. - Aggregate — For each region, print: total number of incidents, average
duration_min(one decimal), and count of unresolved incidents. - Pipeline — Among resolved incidents only, find the service name with the largest sum of
duration_min(tie-breaking: either winner is fine).
Constraints: stdlib only; prefer the patterns above; keep INCIDENTS itself unchanged (build new lists or use queries that do not alter the source dicts).
Step 1 — Filter unresolved P1
Section titled “Step 1 — Filter unresolved P1”Goal: List comprehension or filter for not row["resolved"] and row["severity"] == "P1".
INCIDENTS = [ {"id": "INC-001", "service": "maps-tile-server", "severity": "P1", "region": "us-east", "duration_min": 45, "resolved": True}, {"id": "INC-002", "service": "auth-service", "severity": "P2", "region": "us-west", "duration_min": 20, "resolved": True}, {"id": "INC-003", "service": "geocoder", "severity": "P1", "region": "eu-west", "duration_min": 90, "resolved": False}, {"id": "INC-004", "service": "routing-engine", "severity": "P3", "region": "us-east", "duration_min": 10, "resolved": True}, {"id": "INC-005", "service": "maps-tile-server", "severity": "P2", "region": "eu-west", "duration_min": 30, "resolved": True}, {"id": "INC-006", "service": "search-index", "severity": "P1", "region": "us-west", "duration_min": 60, "resolved": False}, {"id": "INC-007", "service": "auth-service", "severity": "P3", "region": "us-east", "duration_min": 5, "resolved": True}, {"id": "INC-008", "service": "geocoder", "severity": "P2", "region": "us-west", "duration_min": 25, "resolved": True},]
if __name__ == "__main__": open_p1 = [i for i in INCIDENTS if not i["resolved"] and i["severity"] == "P1"] print("Step 1 — open P1 ids:", [i["id"] for i in open_p1])Check: You should see INC-003 and INC-006.
Step 2 — Enrich with sla_breached
Section titled “Step 2 — Enrich with sla_breached”Goal: New dicts via {**row, "sla_breached": ...} so originals stay unchanged.
INCIDENTS = [ {"id": "INC-001", "service": "maps-tile-server", "severity": "P1", "region": "us-east", "duration_min": 45, "resolved": True}, {"id": "INC-002", "service": "auth-service", "severity": "P2", "region": "us-west", "duration_min": 20, "resolved": True}, {"id": "INC-003", "service": "geocoder", "severity": "P1", "region": "eu-west", "duration_min": 90, "resolved": False}, {"id": "INC-004", "service": "routing-engine", "severity": "P3", "region": "us-east", "duration_min": 10, "resolved": True}, {"id": "INC-005", "service": "maps-tile-server", "severity": "P2", "region": "eu-west", "duration_min": 30, "resolved": True}, {"id": "INC-006", "service": "search-index", "severity": "P1", "region": "us-west", "duration_min": 60, "resolved": False}, {"id": "INC-007", "service": "auth-service", "severity": "P3", "region": "us-east", "duration_min": 5, "resolved": True}, {"id": "INC-008", "service": "geocoder", "severity": "P2", "region": "us-west", "duration_min": 25, "resolved": True},]
def with_sla(row): return {**row, "sla_breached": row["duration_min"] > 30}
if __name__ == "__main__": open_p1 = [i for i in INCIDENTS if not i["resolved"] and i["severity"] == "P1"] print("Step 1 — open P1 ids:", [i["id"] for i in open_p1])
enriched = list(map(with_sla, INCIDENTS)) assert "sla_breached" not in INCIDENTS[0] print("Step 2 — first enriched:", enriched[0])Check: First enriched row should include "sla_breached": True for INC-001 (45 > 30).
Step 3 — Group by severity
Section titled “Step 3 — Group by severity”Goal: Reuse a small group_by(data, key) that returns {key_value: [rows...]}.
INCIDENTS = [ {"id": "INC-001", "service": "maps-tile-server", "severity": "P1", "region": "us-east", "duration_min": 45, "resolved": True}, {"id": "INC-002", "service": "auth-service", "severity": "P2", "region": "us-west", "duration_min": 20, "resolved": True}, {"id": "INC-003", "service": "geocoder", "severity": "P1", "region": "eu-west", "duration_min": 90, "resolved": False}, {"id": "INC-004", "service": "routing-engine", "severity": "P3", "region": "us-east", "duration_min": 10, "resolved": True}, {"id": "INC-005", "service": "maps-tile-server", "severity": "P2", "region": "eu-west", "duration_min": 30, "resolved": True}, {"id": "INC-006", "service": "search-index", "severity": "P1", "region": "us-west", "duration_min": 60, "resolved": False}, {"id": "INC-007", "service": "auth-service", "severity": "P3", "region": "us-east", "duration_min": 5, "resolved": True}, {"id": "INC-008", "service": "geocoder", "severity": "P2", "region": "us-west", "duration_min": 25, "resolved": True},]
def with_sla(row): return {**row, "sla_breached": row["duration_min"] > 30}
def group_by(data, key): result = {} for item in data: k = item[key] result.setdefault(k, []).append(item) return result
if __name__ == "__main__": open_p1 = [i for i in INCIDENTS if not i["resolved"] and i["severity"] == "P1"] print("Step 1 — open P1 ids:", [i["id"] for i in open_p1])
enriched = list(map(with_sla, INCIDENTS)) print("Step 2 — first enriched:", enriched[0])
by_sev = group_by(INCIDENTS, "severity") print("Step 3 — ids by severity:") for sev in sorted(by_sev.keys()): print(f" {sev}: {[i['id'] for i in by_sev[sev]]}")Step 4 — Per-region summary
Section titled “Step 4 — Per-region summary”Goal: For each region, print count, average duration, unresolved count.
INCIDENTS = [ {"id": "INC-001", "service": "maps-tile-server", "severity": "P1", "region": "us-east", "duration_min": 45, "resolved": True}, {"id": "INC-002", "service": "auth-service", "severity": "P2", "region": "us-west", "duration_min": 20, "resolved": True}, {"id": "INC-003", "service": "geocoder", "severity": "P1", "region": "eu-west", "duration_min": 90, "resolved": False}, {"id": "INC-004", "service": "routing-engine", "severity": "P3", "region": "us-east", "duration_min": 10, "resolved": True}, {"id": "INC-005", "service": "maps-tile-server", "severity": "P2", "region": "eu-west", "duration_min": 30, "resolved": True}, {"id": "INC-006", "service": "search-index", "severity": "P1", "region": "us-west", "duration_min": 60, "resolved": False}, {"id": "INC-007", "service": "auth-service", "severity": "P3", "region": "us-east", "duration_min": 5, "resolved": True}, {"id": "INC-008", "service": "geocoder", "severity": "P2", "region": "us-west", "duration_min": 25, "resolved": True},]
def with_sla(row): return {**row, "sla_breached": row["duration_min"] > 30}
def group_by(data, key): result = {} for item in data: k = item[key] result.setdefault(k, []).append(item) return result
if __name__ == "__main__": open_p1 = [i for i in INCIDENTS if not i["resolved"] and i["severity"] == "P1"] print("Step 1 — open P1 ids:", [i["id"] for i in open_p1])
enriched = list(map(with_sla, INCIDENTS)) print("Step 2 — first enriched:", enriched[0])
by_sev = group_by(INCIDENTS, "severity") print("Step 3 — ids by severity:") for sev in sorted(by_sev.keys()): print(f" {sev}: {[i['id'] for i in by_sev[sev]]}")
by_region = group_by(INCIDENTS, "region") print("Step 4 — by region:") for region in sorted(by_region.keys()): rows = by_region[region] n = len(rows) avg = sum(r["duration_min"] for r in rows) / n open_n = sum(1 for r in rows if not r["resolved"]) print(f" {region}: count={n} avg_duration={avg:.1f} unresolved={open_n}")Check: eu-west has average 60.0 (two incidents: 90 and 30).
Step 5 — Busiest service among resolved
Section titled “Step 5 — Busiest service among resolved”Goal: Sum duration_min per service over resolved rows only, then take the max.
from functools import reduce
INCIDENTS = [ {"id": "INC-001", "service": "maps-tile-server", "severity": "P1", "region": "us-east", "duration_min": 45, "resolved": True}, {"id": "INC-002", "service": "auth-service", "severity": "P2", "region": "us-west", "duration_min": 20, "resolved": True}, {"id": "INC-003", "service": "geocoder", "severity": "P1", "region": "eu-west", "duration_min": 90, "resolved": False}, {"id": "INC-004", "service": "routing-engine", "severity": "P3", "region": "us-east", "duration_min": 10, "resolved": True}, {"id": "INC-005", "service": "maps-tile-server", "severity": "P2", "region": "eu-west", "duration_min": 30, "resolved": True}, {"id": "INC-006", "service": "search-index", "severity": "P1", "region": "us-west", "duration_min": 60, "resolved": False}, {"id": "INC-007", "service": "auth-service", "severity": "P3", "region": "us-east", "duration_min": 5, "resolved": True}, {"id": "INC-008", "service": "geocoder", "severity": "P2", "region": "us-west", "duration_min": 25, "resolved": True},]
def with_sla(row): return {**row, "sla_breached": row["duration_min"] > 30}
def group_by(data, key): result = {} for item in data: k = item[key] result.setdefault(k, []).append(item) return result
if __name__ == "__main__": open_p1 = [i for i in INCIDENTS if not i["resolved"] and i["severity"] == "P1"] print("Step 1 — open P1 ids:", [i["id"] for i in open_p1])
enriched = list(map(with_sla, INCIDENTS)) print("Step 2 — first enriched:", enriched[0])
by_sev = group_by(INCIDENTS, "severity") print("Step 3 — ids by severity:") for sev in sorted(by_sev.keys()): print(f" {sev}: {[i['id'] for i in by_sev[sev]]}")
by_region = group_by(INCIDENTS, "region") print("Step 4 — by region:") for region in sorted(by_region.keys()): rows = by_region[region] n = len(rows) avg = sum(r["duration_min"] for r in rows) / n open_n = sum(1 for r in rows if not r["resolved"]) print(f" {region}: count={n} avg_duration={avg:.1f} unresolved={open_n}")
resolved = [i for i in INCIDENTS if i["resolved"]] totals = reduce( lambda acc, row: {**acc, row["service"]: acc.get(row["service"], 0) + row["duration_min"]}, resolved, {}, ) busiest = max(totals.items(), key=lambda kv: kv[1]) print("Step 5 — busiest resolved service:", busiest[0], "total_min=", busiest[1])Check: maps-tile-server totals 75 minutes resolved (45 + 30), which beats other services on this dataset.
An equivalent readable formulation is a for loop over resolved that updates a dict of running sums, then max(..., key=...) on totals.items() — use whichever style you find clearer.