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

กราฟโดนัทDonut Chart

เหมือนพาย แต่ได้ที่ว่างกลางไว้ใส่ยอดรวม

1
พื้นฐานควรรู้ก่อน · อ่านกราฟวงกลมเป็น
ลองเล่น

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

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

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

เหมือนเปลี่ยนจากพิซซาเป็นโดนัทที่หั่นเป็นชิ้น เรายังเห็นว่าใครได้ส่วนไหน แต่ตรงกลางมีที่ว่างให้เขียนว่าโดนัททั้งอันหนักกี่กรัม

ใช้ที่ไหนบ้าง — การ์ด KPI ที่ต้องการทั้งยอดรวมและองค์ประกอบ dashboard ที่พื้นที่จำกัด หรือสไลด์ที่อยากให้ยอดรวมเป็นตัวเลขนำ

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

  1. ขั้นที่ 1คำนวณสัดส่วนเหมือนกราฟวงกลม
  2. ขั้นที่ 2เจาะรูกลางประมาณ 50-60% ของรัศมี
  3. ขั้นที่ 3ใส่ยอดรวมหรือตัวเลขนำไว้กลางรู
  4. ขั้นที่ 4ติดป้ายเปอร์เซ็นต์ที่ทุกชิ้น

ตัวอย่างคลาสสิก · โดนัทบนการ์ด KPI ของ dashboard สมัยใหม่

รูปแบบที่พบทั่วไปใน dashboard คือโดนัทที่มีตัวเลขนำอยู่ตรงกลางและองค์ประกอบอยู่รอบวง ซึ่งเป็นการใช้จุดแข็งของโดนัทอย่างตรงจุด คือให้ทั้งคำตอบหลักและบริบทในพื้นที่ของการ์ดใบเดียว

Wikipedia · Pie chart · Doughnut chart

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

ข้อเสียหนึ่งของกราฟวงกลมที่คนมักไม่พูดถึงคือมันซ่อนยอดรวมไว้ ผู้อ่านเห็นว่าส่วนหนึ่งคิดเป็น 40% แต่ไม่รู้เลยว่า 40% ของเท่าไร

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

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

ในทางปฏิบัติความต่างนี้ไม่มาก เพราะกราฟวงกลมเองก็อ่านมุมได้แย่อยู่แล้ว การเลือกระหว่างสองอย่างจึงมักตัดสินที่ว่าต้องการที่ว่างตรงกลางหรือไม่

กติกาอื่นเหมือนกราฟวงกลมทุกประการ คือไม่เกิน 5 ชิ้น ต้องรวมกันเป็นทั้งหมดจริง และต้องติดป้ายเปอร์เซ็นต์เพราะอ่านจากมุมไม่แม่น

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

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

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

คอลัมน์ทำหน้าที่ชนิดเข้ารหัสด้วยจำนวนค่าที่เหมาะหมายเหตุ
categoryส่วนย่อยหมวดหมู่color2–5 ส่วนข้อจำกัดเดียวกับกราฟวงกลม
valueปริมาณตัวเลขต่อเนื่องangleบวกเท่านั้นต้องรวมกันเป็นทั้งหมดจริง

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

  1. ตรวจว่าผลรวมเป็นทั้งหมดจริง
  2. รวมส่วนเล็กเป็น "อื่น ๆ"
  3. เตรียมยอดรวมหรือตัวเลขนำที่จะใส่ตรงกลาง

ค่าที่หายไป — เหมือนกราฟวงกลม คือต้องใส่ชิ้น "ไม่ทราบ" ไว้ให้เห็น ห้ามตัดออกแล้วปรับสัดส่วนที่เหลือ

สเกลของแกน — มุมแปรตรงกับสัดส่วน และขนาดรูไม่ควรเกิน 60% ของรัศมี

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

เกิน 5 ชิ้นเหมือนกราฟวงกลม และถ้ารูใหญ่เกิน 70% ของรัศมี ส่วนโค้งจะบางจนอ่านไม่ได้

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

category,value
กรุงเทพฯ,366
เชียงใหม่,319

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

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

  • ยอดรวมจากตัวเลขตรงกลาง ซึ่งเป็นสิ่งที่กราฟวงกลมซ่อนไว้
  • ส่วนที่ใหญ่ที่สุด
  • สัดส่วนคร่าว ๆ ของแต่ละส่วน

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

  • เทียบชิ้นที่ขนาดใกล้กันไม่ได้ และแม่นน้อยกว่ากราฟวงกลมเล็กน้อยเพราะไม่มีจุดยอดให้อ้างอิง
  • เทียบข้ามโดนัทสองอันไม่ได้ถ้ายอดรวมต่างกัน

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

  1. อ่านยอดรวมตรงกลางก่อน
  2. ดูส่วนที่ใหญ่ที่สุด
  3. อ่านป้ายเปอร์เซ็นต์สำหรับชิ้นที่ใกล้เคียงกัน

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

  • ยอดรวมเท่าไร และแบ่งเป็นส่วนไหนบ้าง
  • ส่วนไหนใหญ่ที่สุด

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

  • รูใหญ่เกินไปจนส่วนโค้งบางมาก
  • ไม่ใส่อะไรตรงกลาง ซึ่งเสียประโยชน์เดียวที่โดนัทมีเหนือกราฟวงกลม
  • มีเกิน 5 ชิ้น

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

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

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

  1. ใส่ยอดรวมเป็นตัวเลขใหญ่ตรงกลางเสมอ นี่คือเหตุผลเดียวที่ใช้โดนัทแทนพาย
  2. ติดป้ายชื่อและเปอร์เซ็นต์ที่ทุกชิ้น
  3. เริ่มชิ้นใหญ่สุดที่ 12 นาฬิกา

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

ยอดรวม <ค่า> โดย <ส่วน> คิดเป็น <เปอร์เซ็นต์>

06เอาไปใช้ต่อ

โค้ดทุกชิ้นอ่านไฟล์ donut-chart-sample.csv ชุดเดียวกับที่ Playground ใช้ และตัวเลขในโค้ดเปลี่ยนตามค่าที่คุณปรับด้านล่าง

# ติดตั้ง: pip install "matplotlib==3.10.*" "pandas==2.*"
# ดาวน์โหลด donut-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("donut-chart-sample.csv")
df["value"] = pd.to_numeric(df["value"], errors="coerce")
SLICES = 5   # ← ค่าจาก Playground

fig, ax = plt.subplots(figsize=(7.6, 4.2), facecolor=SURFACE)
ax.set_facecolor(SURFACE)

d = df.sort_values("value", ascending=False).head(SLICES)
total = d["value"].sum()
ax.pie(d["value"], labels=d["category"], autopct="%1.1f%%", startangle=90, counterclock=False,
       colors=[C1, C2, C3, "#eda100", "#e87ba4"],
       wedgeprops=dict(width=0.42, edgecolor=SURFACE, linewidth=2))   # width < 1 = เจาะรู
ax.text(0, 0.08, "ยอดรวม", ha="center", fontsize=11, color="#52514e")
ax.text(0, -0.12, f"{total:,.0f}", ha="center", fontsize=22)          # ที่ว่างกลางคือเหตุผลที่ใช้โดนัท
ax.set_aspect("equal")

ax.spines[["top", "right"]].set_visible(False)   # ลดเส้นที่ไม่ได้ให้ข้อมูล
fig.tight_layout()
fig.savefig("donut-chart.png", dpi=160)
print("เขียน donut-chart.png แล้ว ·", len(df), "แถว")

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

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

ข้อมูลตัวอย่าง · 8 แถว · seed 42● คำนวณใหม่ในเบราว์เซอร์ทันทีที่ปรับค่า
ชิ้นที่เหลือจะถูกรวมเป็น "อื่น ๆ"
กรุงเทพฯ · 366 (16.8%)ชลบุรี · 328 (15.0%)ขอนแก่น · 321 (14.7%)เชียงใหม่ · 319 (14.6%)ภูเก็ต · 283 (13.0%)อื่น ๆ (3 หมวด) · 566 (25.9%)ยอดรวม2,183กรุงเทพฯ16.8% · 366ชลบุรี15.0% · 328ขอนแก่น14.7% · 321เชียงใหม่14.6% · 319ภูเก็ต13.0% · 283อื่น ๆ (3 หมวด)25.9% · 566

เกิน 5 ส่วนแล้ว มุมที่ใกล้กันแยกด้วยตาไม่ออก — ใช้กราฟแท่งแทนจะอ่านง่ายกว่า

ส่วนที่ใหญ่ที่สุดกรุงเทพฯ · 16.8%
เกินครึ่งหรือไม่ไม่
จำนวนส่วน6
ดูข้อมูลเป็นตาราง (6 แถว)
กราฟโดนัท 6 ส่วน ส่วนใหญ่สุดคือ กรุงเทพฯ ที่ 16.8%
ส่วนค่าสัดส่วน
กรุงเทพฯ36616.8%
ชลบุรี32815.0%
ขอนแก่น32114.7%
เชียงใหม่31914.6%
ภูเก็ต28313.0%
อื่น ๆ (3 หมวด)56625.9%

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

  • จำนวนชิ้นก่อนรวมเป็น "อื่น ๆ": สังเกตว่าไม่ว่าจำนวนชิ้นเปลี่ยนอย่างไร ยอดรวมตรงกลางไม่เปลี่ยน — นั่นคือข้อมูลที่กราฟวงกลมไม่เคยแสดง

ข้อควรระวัง

  1. ไม่ใส่อะไรตรงกลาง ซึ่งเสียประโยชน์เดียวที่โดนัทมีเหนือกราฟวงกลม
  2. เจาะรูใหญ่เกินไปจนส่วนโค้งบางและอ่านสัดส่วนยากมาก
  3. ใส่เกิน 5 ชิ้นเหมือนกราฟวงกลม
  4. ใช้เทียบสองโดนัทที่ยอดรวมต่างกัน

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

  • ไม่มีตัวเลขที่จะใส่ตรงกลางใช้แทน: pie-chart หรือดีกว่านั้นคือ horizontal-bar
  • มีมากกว่า 5 ส่วนใช้แทน: horizontal-bar
  • ต้องการเทียบสัดส่วนข้ามกลุ่มใช้แทน: percent-stacked-bar

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

เทคนิคถัดไป · แผนภาพต้นไม้