When you need to monitor variation in inquiries or yield rates, control charts are effective. Plotting statistical control limits helps detect anomalies immediately.
import numpy as np
import matplotlib.pyplot as plt
rng = np.random.default_rng(5)
values = 45 + rng.normal(0, 3, size=28)
values[[6, 18]] += np.array([12, -10]) # Inject anomalies
mean = values.mean()
std = values.std(ddof=1)
ucl = mean + 3 * std
lcl = mean - 3 * std
fig, ax = plt.subplots(figsize=(6.4, 3.6))
ax.plot(values, marker="o", color="#0ea5e9")
ax.axhline(mean, color="#334155", linewidth=1.3, label="Mean")
ax.axhline(ucl, color="#ef4444", linestyle="--", label="UCL")
ax.axhline(lcl, color="#ef4444", linestyle="--", label="LCL")
ax.set_xticks(range(0, len(values), 4), labels=[f"W{i+1}" for i in range(0, len(values), 4)])
ax.set_title("Control chart of call handling time")
ax.set_ylabel("Average handling time (sec)")
ax.grid(alpha=0.2)
for idx, val in enumerate(values):
if val > ucl or val < lcl:
ax.annotate(
"Anomaly",
(idx, val),
xytext=(idx + 0.5, val + 4),
arrowprops=dict(arrowstyle="->", color="#ef4444"),
color="#ef4444",
)
ax.legend(loc="upper right")
fig.tight_layout()
plt.show()

Reading tips #
- Draw control limits (±3σ) around the mean to flag statistically abnormal points.
- If anomalies persist, the process may have shifted; investigate root causes.
- Adjust line style and markers to match the tone of your report.