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

กราฟอมยิ้มLollipop Chart

อ่านอันดับได้เหมือนแท่ง แต่ภาพโปร่งกว่ามาก

2
ต่อยอดโดยตรงควรรู้ก่อน · อ่านกราฟแท่งเป็น
ลองเล่น

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

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

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

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

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

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

  1. ขั้นที่ 1เรียงจากมากไปน้อย
  2. ขั้นที่ 2ลากก้านจากศูนย์ถึงค่า
  3. ขั้นที่ 3วาดหัวกลมที่ตำแหน่งค่า
  4. ขั้นที่ 4ติดตัวเลขข้างหัว

ตัวอย่างคลาสสิก · กราฟจัดอันดับที่ต้องการ data-ink ratio สูง

Edward Tufte เสนอแนวคิด data-ink ratio ว่าหมึกทุกหยดบนภาพควรสื่อข้อมูล lollipop chart คือผลโดยตรงของแนวคิดนี้ที่ใช้กับกราฟแท่ง เพราะพื้นที่สีทึบของแท่งไม่ได้เพิ่มข้อมูลเกินกว่าที่ตำแหน่งปลายแท่งบอกอยู่แล้ว

Edward Tufte · The Visual Display of Quantitative Information

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

เวลาจัดอันดับ 20-30 รายการด้วยกราฟแท่ง ภาพจะเต็มไปด้วยพื้นที่สีจนดูหนักและทึบ ทั้งที่ข้อมูลจริงที่เราต้องการคือแค่ "ค่าของแต่ละรายการอยู่ตรงไหน"

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

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

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

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

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

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

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

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

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

  1. เรียงตามค่า
  2. ตัดสินใจว่าจะลากก้านจากศูนย์หรือจากค่าอ้างอิงอื่น
  3. ระบุค่าอ้างอิงนั้นใน caption

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

สเกลของแกน — linear เมื่อก้านลากจากศูนย์ ถ้าอยากใช้ log ต้องตัดก้านออกและเปลี่ยนเป็น dot-plot

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

เกิน 40 รายการ ก้านจะชิดกันจนดูเป็นแรเงา — ใช้ ranking-table หรือ data-table-viz แทน

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

category,value

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

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

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

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

  • ไม่บอกการเปลี่ยนแปลงตามเวลา
  • ไม่บอกว่าความต่างเล็ก ๆ ที่เห็นมีนัยสำคัญหรือไม่

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

  1. ดูจุดบนสุดก่อน
  2. กวาดตาลงตามตำแหน่งของจุด ไม่ใช่ตามความยาวก้าน
  3. หาช่องว่างกว้าง ๆ ระหว่างจุด ซึ่งคือเส้นแบ่งกลุ่มธรรมชาติ

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

  • อันดับหนึ่งคือใคร
  • รายการเหล่านี้แบ่งเป็นกี่กลุ่มโดยธรรมชาติ
  • รายการที่เราสนใจห่างจากอันดับหนึ่งเท่าไร

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

  • ตัดแกนไม่ให้เริ่มที่ศูนย์ทั้งที่ยังมีก้าน
  • ไม่เรียงลำดับ
  • หัวจุดใหญ่จนบังความต่างระหว่างรายการที่ใกล้กัน

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

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

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

  1. ระบายสีหัวจุดของรายการที่สนใจให้ต่างจากที่เหลือ
  2. ติดตัวเลขข้างหัวจุดได้ทุกรายการเพราะมีที่ว่าง
  3. ถ้ามีค่าอ้างอิง ให้ลากเส้นแนวตั้งของค่านั้นพาดผ่าน

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

<รายการ> นำอันดับหนึ่งที่ <ค่า> โดยกลุ่มนำมี <จำนวน> รายการที่ค่าใกล้เคียงกัน

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

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

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

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

d = df.sort_values("value")
ax.hlines(d["category"], 0, d["value"], color="#9ec5f4", linewidth=2)   # ก้านบาง
ax.plot(d["value"], d["category"], "o", markersize=9, color=C1)          # หัวคือสิ่งที่อ่านค่า
ax.set_xlim(0, None)
ax.set_xlabel("ยอดขาย (ล้านบาท)")
ax.grid(axis="x", alpha=0.25); ax.set_axisbelow(True)

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

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

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

ข้อมูลตัวอย่าง · 12 แถว · seed 42● คำนวณใหม่ในเบราว์เซอร์ทันทีที่ปรับค่า
ลำดับของแถว
กรุงเทพฯชลบุรีขอนแก่นเชียงใหม่ภูเก็ตสงขลานครราชสีมาสุราษฎร์ธานีอุดรธานีพิษณุโลกระยองนครปฐม0.00100200300400500600กรุงเทพฯ · 502ชลบุรี · 464ขอนแก่น · 457เชียงใหม่ · 455ภูเก็ต · 419สงขลา · 363นครราชสีมา · 344สุราษฎร์ธานี · 275อุดรธานี · 267พิษณุโลก · 216ระยอง · 183นครปฐม · 172502
อันดับ 1กรุงเทพฯ
ค่าสูงสุด502
จำนวนหมวด12
ดูข้อมูลเป็นตาราง (12 แถว)
กราฟแนวนอนเรียงอันดับ 12 หมวด อันดับหนึ่งคือ กรุงเทพฯ
หมวดค่า
กรุงเทพฯ502
ชลบุรี464
ขอนแก่น457
เชียงใหม่455
ภูเก็ต419
สงขลา363
นครราชสีมา344
สุราษฎร์ธานี275
อุดรธานี267
พิษณุโลก216
ระยอง183
นครปฐม172

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

  • การเรียงลำดับ: เรียงตามค่าแล้วจะเห็นช่องว่างที่แบ่งรายการเป็นกลุ่ม ๆ ซึ่งเป็นสิ่งที่เรียงตามตัวอักษรซ่อนไว้

ข้อควรระวัง

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

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

  • มีน้อยกว่า 5 รายการใช้แทน: bar-chart ที่คุ้นเคยกว่า
  • ต้องการตัดแกนเพราะค่าเกาะกลุ่มกันสูงใช้แทน: dot-plot ที่ไม่มีก้านจึงตัดแกนได้
  • ต้องเทียบสองช่วงเวลาใช้แทน: dumbbell-chart

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

เทคนิคถัดไป · กราฟจุดคลีฟแลนด์