เมื่ออยากแสดง KPI หลายตัวพร้อมช่องว่างจากเป้าหมาย บูลเล็ตชาร์ตช่วยประหยัดพื้นที่ได้ดี พื้นที่พื้นหลังเป็นแถบยังบอกระดับการบรรลุเป้าหมายได้ในตัว
import matplotlib.pyplot as plt
import numpy as np
metrics = ["CVR", "มูลค่าต่อคำสั่งซื้อเฉลี่ย", "อัตราคงอยู่ของสมาชิก", "NPS"]
actual = np.array([0.046, 12_300, 0.78, 32])
target = np.array([0.05, 12_000, 0.8, 35])
thresholds = np.array(
[
[0.02, 0.04, 0.06],
[9000, 11_000, 13_500],
[0.6, 0.75, 0.85],
[10, 25, 40],
]
)
fig, ax = plt.subplots(figsize=(6.2, 4))
for idx, name in enumerate(metrics):
base, good, excellent = thresholds[idx]
ax.barh(idx, excellent, color="#f1f5f9", height=0.8)
ax.barh(idx, good, color="#cbd5f5", height=0.8)
ax.barh(idx, base, color="#94a3b8", height=0.8)
ax.barh(idx, actual[idx], color="#38bdf8", height=0.3)
ax.plot(
[target[idx], target[idx]],
[idx - 0.4, idx + 0.4],
color="#ef4444",
linewidth=2,
)
ax.text(
actual[idx] * 1.02,
idx,
f"{actual[idx]:.2f}" if idx != 1 else f"{actual[idx]:,.0f}",
va="center",
ha="left",
fontsize=9,
)
ax.set_yticks(range(len(metrics)), labels=metrics)
ax.set_xlabel("ค่าตัวชี้วัด")
ax.set_title("ความคืบหน้า KPI หลัก (บูลเล็ตชาร์ต)")
ax.set_xlim(0, max(thresholds[:, -1]) * 1.05)
ax.grid(axis="x", alpha=0.2)
ax.spines[["right", "top"]].set_visible(False)
fig.tight_layout()
plt.show()

อ่านอย่างไร #
- แถบพื้นหลังคือโซนระดับการบรรลุเป้าหมาย ถ้าแท่งถึงแถบสีเข้มแปลว่าทะลุเป้าหมายระดับสูง
- เส้นสีแดงคือค่าเป้าหมาย หากแท่งเลยเส้นคือทำเกินเป้า หากไม่ถึงคือยังไม่ถึงเป้า
- รวมหลาย KPI ในหน้าเดียวได้ เหมาะกับรายงานสรุปรายสัปดาห์