01ภาพรวมของกราฟนี้
Bullet chart คือแถบแนวนอนที่ซ้อนข้อมูลสามชั้น พื้นหลังไล่เฉดบอกช่วงมาตรฐาน แถบทึบบอกค่าที่ทำได้จริง และขีดตั้งบอกเป้าหมาย Stephen Few ออกแบบมาแทนเกจวัดโดยเฉพาะ เพราะเกจใช้พื้นที่มากเพื่อแสดงตัวเลขเดียว
เปรียบเทียบให้เห็นภาพ
เหมือนเทอร์โมมิเตอร์ที่มีขีดบอกอุณหภูมิเป้าหมายและมีแถบสีบอกว่าช่วงไหนคือปกติ ร้อน หรือร้อนจัด อ่านครั้งเดียวได้ครบทุกอย่าง
ใช้ที่ไหนบ้าง — dashboard ติดตาม KPI รายงานผลเทียบเป้าไตรมาส หรือหน้าสรุปที่ต้องวางตัวชี้วัดหลายตัวเรียงกัน
สร้างอย่างไร
- ขั้นที่ 1กำหนดช่วงมาตรฐาน เช่น ต่ำ ปานกลาง ดี
- ขั้นที่ 2วาดพื้นหลังไล่เฉดตามช่วง
- ขั้นที่ 3วาดแถบทึบของค่าที่ทำได้
- ขั้นที่ 4ปักขีดตั้งที่ตำแหน่งเป้าหมาย
ตัวอย่างคลาสสิก · Stephen Few ออกแบบมาแทนเกจวัดบน dashboard โดยเฉพาะ
Few ชี้ว่าเกจวัดแบบเข็มยืมภาพมาจากหน้าปัดรถยนต์โดยไม่ได้คิดว่าบริบทต่างกัน เกจในรถต้องอ่านด้วยหางตาขณะขับ แต่ dashboard ธุรกิจอ่านด้วยตาเต็ม ๆ เขาจึงเสนอ bullet graph ที่ใช้พื้นที่หนึ่งในสี่แต่ใส่บริบทได้มากกว่า
02อธิบายภาษาคนเข้าใจง่าย ๆ
ปัญหาของเกจวัดแบบเข็มคือมันกินพื้นที่เป็นวงกลมใหญ่เพื่อบอกตัวเลขเดียว ถ้ามี KPI 6 ตัวก็ต้องวางเกจ 6 วง ซึ่งกินทั้งหน้าจอโดยที่ข้อมูลจริงมีแค่ 6 ตัวเลข
Bullet chart แก้ด้วยการยุบเกจให้แบนเป็นแถบแนวนอน ทีนี้วาง KPI หลายตัวเรียงกันในแนวตั้งได้ และเพราะทุกตัวใช้แถบหน้าตาเดียวกัน คนอ่านจึงเทียบข้ามตัวชี้วัดได้ทันที
ที่สำคัญกว่าคือมันใส่ข้อมูลได้มากกว่าเกจ พื้นหลังไล่เฉดบอกว่าช่วงไหนถือว่าแย่ พอใช้ได้ หรือดี ซึ่งเป็นบริบทที่เกจทั่วไปไม่มี ทำให้ตัวเลข 72 มีความหมายขึ้นมาทันที
ขีดตั้งคือเป้าหมาย และเป็นสิ่งที่ตาจับได้ไวที่สุดในภาพ คนอ่านจึงตอบได้ใน 0.5 วินาทีว่าถึงเป้าหรือยัง ซึ่งเป็นคำถามแรกที่ทุกคนถามกับ KPI
ข้อควรระวังคือช่วงมาตรฐานต้องมีที่มาจริง ไม่ใช่แบ่งสามส่วนเท่า ๆ กันตามใจ เพราะพื้นหลังไล่เฉดจะกลายเป็นการตัดสินที่ไม่มีหลักฐานรองรับ ภาพจำคือ ถ้าอธิบายที่มาของช่วงไม่ได้ ก็อย่าใส่ช่วง
03ข้อมูลที่ต้องใช้
คอลัมน์ที่ต้องเตรียม
| คอลัมน์ | ทำหน้าที่ | ชนิด | เข้ารหัสด้วย | จำนวนค่าที่เหมาะ | หมายเหตุ |
|---|---|---|---|---|---|
category | ตัวชี้วัด | หมวดหมู่ | y | 3–8 ตัว | เกิน 8 ตัวหน้าจะยาวจนเทียบหัวท้ายไม่ได้ |
value | ค่าที่ทำได้จริง | ตัวเลขต่อเนื่อง | x | ต่อเนื่อง | หน่วยของแต่ละตัวชี้วัดต่างกันได้ เพราะแต่ละแถบมีสเกลของตัวเอง |
target | เป้าหมาย | ตัวเลขต่อเนื่อง | x | หนึ่งค่าต่อตัวชี้วัด | ต้องเป็นหน่วยเดียวกับ value |
ต้องเตรียมข้อมูลอย่างไรก่อนวาด
- กำหนดช่วงมาตรฐานพร้อมที่มาที่อธิบายได้
- ตรวจว่า value กับ target เป็นหน่วยเดียวกัน
- ตัดสินใจว่าปลายสเกลของแต่ละแถบควรอยู่ที่เท่าไร
ค่าที่หายไป — ตัวชี้วัดที่ไม่มีเป้าหมายให้วาดแถบโดยไม่มีขีด และเขียนว่า "ยังไม่ตั้งเป้า" เพื่อไม่ให้ผู้อ่านคิดว่าลืมใส่
สเกลของแกน — linear เริ่มที่ศูนย์ แต่ละแถบมีสเกลของตัวเองได้เพราะไม่ได้ให้เทียบความยาวข้ามแถบ
กราฟจะเริ่มพังเมื่อไร
เกิน 10 ตัวชี้วัด ควรแยกเป็นหลายกลุ่มหรือใช้ data-table-viz แทน
หน้าตาไฟล์ที่ต้องเตรียม
date,value,target
…04อ่านแล้วเห็นอะไร
สิ่งที่เห็นได้จากภาพ
- ตัวชี้วัดไหนถึงเป้าและตัวไหนยังไม่ถึง
- ห่างจากเป้าอยู่เท่าไรในหน่วยจริง
- ค่าที่ทำได้ตกอยู่ในช่วงมาตรฐานไหน
- ตัวชี้วัดที่ห่างเป้ามากที่สุด
สิ่งที่กราฟนี้ตอบไม่ได้
- ไม่บอกว่าเปลี่ยนแปลงอย่างไรตามเวลา ต้องเพิ่ม sparkline ข้าง ๆ
- ไม่บอกว่าห่างจากเป้าเพราะอะไร
- ไม่บอกว่าเป้านั้นตั้งไว้สมเหตุสมผลหรือไม่
อ่านตามลำดับนี้
- หาขีดตั้งซึ่งคือเป้าหมายก่อน
- ดูว่าแถบทึบเลยขีดหรือยัง
- ดูว่าปลายแถบอยู่ในช่วงเฉดไหน
- เทียบระยะที่ขาดกับความยาวรวม
คำถามที่ตอบได้
- ถึงเป้าหรือยัง
- ตัวไหนน่าเป็นห่วงที่สุด
- ทำได้กี่เปอร์เซ็นต์ของเป้า
สัญญาณว่ามีอะไรผิด
- ช่วงมาตรฐานแบ่งเท่า ๆ กันโดยไม่มีที่มา
- ปลายสเกลตั้งไว้สูงเกินจริงจนทุกแถบดูสั้น
- ไม่มีหน่วยกำกับ
05เหมาะกับการนำเสนอแบบไหน
ทำอย่างไรให้คนอ่านได้ข้อสรุปโดยไม่ต้องบรรยาย
- เขียนค่าที่ทำได้และเป้าเป็นตัวเลขไว้ท้ายแถบ
- อธิบายที่มาของช่วงมาตรฐานไว้ใน caption
- ใช้สีเขียวเฉพาะตอนถึงเป้า เพื่อให้สีมีความหมายจริง
รูปแบบชื่อกราฟที่ควรใช้
<จำนวน> จาก <ทั้งหมด> ตัวชี้วัดถึงเป้า โดย <ตัวชี้วัด> ห่างเป้ามากที่สุดที่ <ส่วนต่าง>
06เอาไปใช้ต่อ
โค้ดทุกชิ้นอ่านไฟล์ bullet-chart-sample.csv ชุดเดียวกับที่ Playground ใช้ และตัวเลขในโค้ดเปลี่ยนตามค่าที่คุณปรับด้านล่าง
# ติดตั้ง: pip install "matplotlib==3.10.*" "pandas==2.*"
# ดาวน์โหลด bullet-chart-sample.csv จากหน้านี้ แล้ววางไว้ข้างสคริปต์
import matplotlib
matplotlib.use("Agg") # รันแบบไม่มีหน้าจอ ถ้ารันในเครื่องตัวเองลบบรรทัดนี้ได้
import matplotlib.pyplot as plt
import pandas as pd
C1, C2, C3 = "#2a78d6", "#eb6834", "#1baf7a" # palette ของคลัง เปลี่ยนเป็นสีองค์กรได้
INK, SURFACE = "#0b0b0b", "#fcfcfb"
df = pd.read_csv("bullet-chart-sample.csv")
df["value"] = pd.to_numeric(df["value"], errors="coerce")
df["target"] = pd.to_numeric(df["target"], errors="coerce")
NOTE = "target" # ← ค่าจาก Playground
fig, ax = plt.subplots(figsize=(7.6, 4.2), facecolor=SURFACE)
ax.set_facecolor(SURFACE)
d = df.tail(5).reset_index(drop=True)
for i, r in d.iterrows():
for q, shade in zip([1.0, 0.85, 0.6], ["#cde2fb", "#9ec5f4", "#6da7ec"]):
ax.barh(i, r["target"] * q, height=0.62, color=shade, zorder=1) # ช่วงมาตรฐาน
ax.barh(i, r["value"], height=0.26, color=C1, zorder=2) # ค่าที่ทำได้
ax.plot([r["target"], r["target"]], [i - 0.33, i + 0.33], color=INK, linewidth=2.6, zorder=3)
ax.set_yticks(range(len(d))); ax.set_yticklabels([f"สัปดาห์ {i+1}" for i in range(len(d))])
ax.set_xlim(0, None); ax.set_xlabel("ค่าที่ทำได้ · ขีดดำคือเป้าหมาย")
ax.spines[["top", "right"]].set_visible(False) # ลดเส้นที่ไม่ได้ให้ข้อมูล
fig.tight_layout()
fig.savefig("bullet-chart.png", dpi=160)
print("เขียน bullet-chart.png แล้ว ·", len(df), "แถว")07ลองเล่นเพื่อเข้าใจ
ดูข้อมูลเป็นตาราง (5 แถว)
| ตัวชี้วัด | ทำได้ | เป้า | % ของเป้า |
|---|---|---|---|
| undefined | 61.9 | 86.0 | 72% |
| undefined | 64.0 | 86.0 | 74% |
| undefined | 62.6 | 86.0 | 73% |
| undefined | 62.2 | 86.0 | 72% |
| undefined | 62.4 | 86.0 | 73% |
ลองแล้วจะเห็นอะไร
- สังเกตอะไร: สังเกตว่าสายตาจับ "ขีดเป้า" ได้ก่อนตัวเลขเสมอ นี่คือเหตุผลที่กราฟนี้เหมาะกับ dashboard ที่คนดูผ่าน ๆ
ข้อควรระวัง
- แบ่งช่วงมาตรฐานเท่า ๆ กันโดยไม่มีที่มา ทำให้พื้นหลังกลายเป็นการตัดสินที่ไม่มีหลักฐาน
- ใส่ตัวชี้วัดเกิน 8 ตัวจนหน้ายาวและเทียบไม่ได้
- ใช้สีสถานะอย่างเขียวแดงกับแถบทุกแถบ ทำให้สีหมดความหมาย
- ตั้งปลายสเกลสูงเกินจริงจนทุกแถบดูสั้นและไม่ต่างกัน
เมื่อไหร่ไม่ควรใช้กราฟนี้
- มีตัวชี้วัดเดียวและพื้นที่เหลือเฟือ→ใช้แทน: stat-tile ที่มี sparkline ให้เห็นแนวโน้มด้วย
- ไม่มีเป้าหมายที่ชัดเจน→ใช้แทน: horizontal-bar ธรรมดา
- ต้องการเห็นแนวโน้มด้วย→ใช้แทน: sparkline-tile หรือ line-chart ที่มีเส้นเป้า