เทคนิคที่ 010 · PYTHON / JAVASCRIPT

กราฟกระสุนBullet Chart

แทนเกจกลม ให้ข้อมูลมากกว่าในพื้นที่ครึ่งเดียว

3
ผสานหลายแนวคิดควรรู้ก่อน · อ่านกราฟแท่งเป็น และรู้ว่าเป้าหมายของตัวชี้วัดคืออะไร
ลองเล่น

01ภาพรวมของกราฟนี้

Bullet chart คือแถบแนวนอนที่ซ้อนข้อมูลสามชั้น พื้นหลังไล่เฉดบอกช่วงมาตรฐาน แถบทึบบอกค่าที่ทำได้จริง และขีดตั้งบอกเป้าหมาย Stephen Few ออกแบบมาแทนเกจวัดโดยเฉพาะ เพราะเกจใช้พื้นที่มากเพื่อแสดงตัวเลขเดียว

เปรียบเทียบให้เห็นภาพ

เหมือนเทอร์โมมิเตอร์ที่มีขีดบอกอุณหภูมิเป้าหมายและมีแถบสีบอกว่าช่วงไหนคือปกติ ร้อน หรือร้อนจัด อ่านครั้งเดียวได้ครบทุกอย่าง

ใช้ที่ไหนบ้าง — dashboard ติดตาม KPI รายงานผลเทียบเป้าไตรมาส หรือหน้าสรุปที่ต้องวางตัวชี้วัดหลายตัวเรียงกัน

สร้างอย่างไร

  1. ขั้นที่ 1กำหนดช่วงมาตรฐาน เช่น ต่ำ ปานกลาง ดี
  2. ขั้นที่ 2วาดพื้นหลังไล่เฉดตามช่วง
  3. ขั้นที่ 3วาดแถบทึบของค่าที่ทำได้
  4. ขั้นที่ 4ปักขีดตั้งที่ตำแหน่งเป้าหมาย

ตัวอย่างคลาสสิก · Stephen Few ออกแบบมาแทนเกจวัดบน dashboard โดยเฉพาะ

Few ชี้ว่าเกจวัดแบบเข็มยืมภาพมาจากหน้าปัดรถยนต์โดยไม่ได้คิดว่าบริบทต่างกัน เกจในรถต้องอ่านด้วยหางตาขณะขับ แต่ dashboard ธุรกิจอ่านด้วยตาเต็ม ๆ เขาจึงเสนอ bullet graph ที่ใช้พื้นที่หนึ่งในสี่แต่ใส่บริบทได้มากกว่า

Stephen Few · Bullet Graph Design Specification

02อธิบายภาษาคนเข้าใจง่าย ๆ

ปัญหาของเกจวัดแบบเข็มคือมันกินพื้นที่เป็นวงกลมใหญ่เพื่อบอกตัวเลขเดียว ถ้ามี KPI 6 ตัวก็ต้องวางเกจ 6 วง ซึ่งกินทั้งหน้าจอโดยที่ข้อมูลจริงมีแค่ 6 ตัวเลข

Bullet chart แก้ด้วยการยุบเกจให้แบนเป็นแถบแนวนอน ทีนี้วาง KPI หลายตัวเรียงกันในแนวตั้งได้ และเพราะทุกตัวใช้แถบหน้าตาเดียวกัน คนอ่านจึงเทียบข้ามตัวชี้วัดได้ทันที

ที่สำคัญกว่าคือมันใส่ข้อมูลได้มากกว่าเกจ พื้นหลังไล่เฉดบอกว่าช่วงไหนถือว่าแย่ พอใช้ได้ หรือดี ซึ่งเป็นบริบทที่เกจทั่วไปไม่มี ทำให้ตัวเลข 72 มีความหมายขึ้นมาทันที

ขีดตั้งคือเป้าหมาย และเป็นสิ่งที่ตาจับได้ไวที่สุดในภาพ คนอ่านจึงตอบได้ใน 0.5 วินาทีว่าถึงเป้าหรือยัง ซึ่งเป็นคำถามแรกที่ทุกคนถามกับ KPI

ข้อควรระวังคือช่วงมาตรฐานต้องมีที่มาจริง ไม่ใช่แบ่งสามส่วนเท่า ๆ กันตามใจ เพราะพื้นหลังไล่เฉดจะกลายเป็นการตัดสินที่ไม่มีหลักฐานรองรับ ภาพจำคือ ถ้าอธิบายที่มาของช่วงไม่ได้ ก็อย่าใส่ช่วง

03ข้อมูลที่ต้องใช้

รูปทรงของข้อมูลตารางแบบยาว (หนึ่งแถวหนึ่งสังเกต)
จำนวนมิติที่เข้ารหัสได้3 มิติ
จำนวนแถวที่เหมาะ3–6 ตัวชี้วัดขั้นต่ำ 2 แถว
เส้นฐานศูนย์ต้องเริ่มที่ศูนย์แถบทึบสื่อความยาวจากศูนย์ถึงค่าที่ทำได้

คอลัมน์ที่ต้องเตรียม

คอลัมน์ทำหน้าที่ชนิดเข้ารหัสด้วยจำนวนค่าที่เหมาะหมายเหตุ
categoryตัวชี้วัดหมวดหมู่y3–8 ตัวเกิน 8 ตัวหน้าจะยาวจนเทียบหัวท้ายไม่ได้
valueค่าที่ทำได้จริงตัวเลขต่อเนื่องxต่อเนื่องหน่วยของแต่ละตัวชี้วัดต่างกันได้ เพราะแต่ละแถบมีสเกลของตัวเอง
targetเป้าหมายตัวเลขต่อเนื่องxหนึ่งค่าต่อตัวชี้วัดต้องเป็นหน่วยเดียวกับ value

ต้องเตรียมข้อมูลอย่างไรก่อนวาด

  1. กำหนดช่วงมาตรฐานพร้อมที่มาที่อธิบายได้
  2. ตรวจว่า value กับ target เป็นหน่วยเดียวกัน
  3. ตัดสินใจว่าปลายสเกลของแต่ละแถบควรอยู่ที่เท่าไร

ค่าที่หายไป — ตัวชี้วัดที่ไม่มีเป้าหมายให้วาดแถบโดยไม่มีขีด และเขียนว่า "ยังไม่ตั้งเป้า" เพื่อไม่ให้ผู้อ่านคิดว่าลืมใส่

สเกลของแกน — linear เริ่มที่ศูนย์ แต่ละแถบมีสเกลของตัวเองได้เพราะไม่ได้ให้เทียบความยาวข้ามแถบ

กราฟจะเริ่มพังเมื่อไร

เกิน 10 ตัวชี้วัด ควรแยกเป็นหลายกลุ่มหรือใช้ data-table-viz แทน

หน้าตาไฟล์ที่ต้องเตรียม

date,value,target

04อ่านแล้วเห็นอะไร

สิ่งที่เห็นได้จากภาพ

  • ตัวชี้วัดไหนถึงเป้าและตัวไหนยังไม่ถึง
  • ห่างจากเป้าอยู่เท่าไรในหน่วยจริง
  • ค่าที่ทำได้ตกอยู่ในช่วงมาตรฐานไหน
  • ตัวชี้วัดที่ห่างเป้ามากที่สุด

สิ่งที่กราฟนี้ตอบไม่ได้

  • ไม่บอกว่าเปลี่ยนแปลงอย่างไรตามเวลา ต้องเพิ่ม sparkline ข้าง ๆ
  • ไม่บอกว่าห่างจากเป้าเพราะอะไร
  • ไม่บอกว่าเป้านั้นตั้งไว้สมเหตุสมผลหรือไม่

อ่านตามลำดับนี้

  1. หาขีดตั้งซึ่งคือเป้าหมายก่อน
  2. ดูว่าแถบทึบเลยขีดหรือยัง
  3. ดูว่าปลายแถบอยู่ในช่วงเฉดไหน
  4. เทียบระยะที่ขาดกับความยาวรวม

คำถามที่ตอบได้

  • ถึงเป้าหรือยัง
  • ตัวไหนน่าเป็นห่วงที่สุด
  • ทำได้กี่เปอร์เซ็นต์ของเป้า

สัญญาณว่ามีอะไรผิด

  • ช่วงมาตรฐานแบ่งเท่า ๆ กันโดยไม่มีที่มา
  • ปลายสเกลตั้งไว้สูงเกินจริงจนทุกแถบดูสั้น
  • ไม่มีหน่วยกำกับ

05เหมาะกับการนำเสนอแบบไหน

ผู้ชมที่เหมาะทีมที่ติดตาม KPI เป็นประจำและรู้ว่าเป้าคืออะไร
เวลาที่ผู้ชมต้องใช้ไม่กี่วินาที
ขนาดเล็กสุดที่ยังอ่านได้360×200 px
dashboard ที่อัปเดตตลอด
สไลด์ผู้บริหาร
สิ่งพิมพ์
รายงานเชิงวิเคราะห์
สื่อสารกับคนทั่วไปต้องอธิบายว่าขีดคืออะไรและเฉดหมายถึงอะไรก่อน

ทำอย่างไรให้คนอ่านได้ข้อสรุปโดยไม่ต้องบรรยาย

  1. เขียนค่าที่ทำได้และเป้าเป็นตัวเลขไว้ท้ายแถบ
  2. อธิบายที่มาของช่วงมาตรฐานไว้ใน caption
  3. ใช้สีเขียวเฉพาะตอนถึงเป้า เพื่อให้สีมีความหมายจริง

รูปแบบชื่อกราฟที่ควรใช้

<จำนวน> จาก <ทั้งหมด> ตัวชี้วัดถึงเป้า โดย <ตัวชี้วัด> ห่างเป้ามากที่สุดที่ <ส่วนต่าง>

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), "แถว")

ติดตั้ง: pip install "matplotlib==3.10.*" "pandas==2.*" · ทดสอบกับเวอร์ชัน 3.10

07ลองเล่นเพื่อเข้าใจ

ข้อมูลตัวอย่าง · 5 แถว · seed 5● คำนวณใหม่ในเบราว์เซอร์ทันทีที่ปรับค่า
ขีดดำคือเป้า เฉดพื้นหลังคือช่วงมาตรฐาน
ค่าที่ทำได้เป้าหมาย (เส้นดำ)ช่วงมาตรฐาน
0.0020.040.060.080.0100undefined · ทำได้ 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%)undefinedundefinedundefinedundefinedundefined
ถึงเป้า0 จาก 5
ตัวที่ห่างเป้ามากสุดundefined
ค่าเฉลี่ย % ของเป้า73%
ดูข้อมูลเป็นตาราง (5 แถว)
bullet chart 5 ตัวชี้วัด ถึงเป้า 0 ตัว
ตัวชี้วัดทำได้เป้า% ของเป้า
undefined61.986.072%
undefined64.086.074%
undefined62.686.073%
undefined62.286.072%
undefined62.486.073%

ลองแล้วจะเห็นอะไร

  • สังเกตอะไร: สังเกตว่าสายตาจับ "ขีดเป้า" ได้ก่อนตัวเลขเสมอ นี่คือเหตุผลที่กราฟนี้เหมาะกับ dashboard ที่คนดูผ่าน ๆ

ข้อควรระวัง

  1. แบ่งช่วงมาตรฐานเท่า ๆ กันโดยไม่มีที่มา ทำให้พื้นหลังกลายเป็นการตัดสินที่ไม่มีหลักฐาน
  2. ใส่ตัวชี้วัดเกิน 8 ตัวจนหน้ายาวและเทียบไม่ได้
  3. ใช้สีสถานะอย่างเขียวแดงกับแถบทุกแถบ ทำให้สีหมดความหมาย
  4. ตั้งปลายสเกลสูงเกินจริงจนทุกแถบดูสั้นและไม่ต่างกัน

เมื่อไหร่ไม่ควรใช้กราฟนี้

  • มีตัวชี้วัดเดียวและพื้นที่เหลือเฟือใช้แทน: stat-tile ที่มี sparkline ให้เห็นแนวโน้มด้วย
  • ไม่มีเป้าหมายที่ชัดเจนใช้แทน: horizontal-bar ธรรมดา
  • ต้องการเห็นแนวโน้มด้วยใช้แทน: sparkline-tile หรือ line-chart ที่มีเส้นเป้า

กราฟที่เกี่ยวข้อง

เทคนิคถัดไป · กราฟแท่งรัศมี