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

กราฟแท่งBar Chart

เทียบปริมาณข้ามหมวดด้วยความยาวที่ตาอ่านแม่นที่สุด

1
พื้นฐานควรรู้ก่อน · ไม่ต้องมีพื้นฐานมาก่อน
ลองเล่น

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

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

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

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

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

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

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

ตัวอย่างคลาสสิก · แผนภูมิแท่งของ William Playfair ปี 1786 — กราฟแท่งชิ้นแรกของโลก

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

Wikipedia · Bar chart (ประวัติและที่มา)

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

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

เหตุผลที่กราฟแท่งอ่านง่ายเป็นพิเศษคือมันใช้ "ความยาวบนเส้นฐานเดียวกัน" ซึ่งเป็นสิ่งที่สายตามนุษย์อ่านได้แม่นที่สุด แม่นกว่ามุมของกราฟวงกลม แม่นกว่าขนาดพื้นที่ของวงกลม และแม่นกว่าความเข้มของสี

ข้อบังคับที่ห้ามละเมิดคือแกนค่าต้องเริ่มที่ศูนย์ เพราะเรากำลังให้คนอ่านค่าจากความยาว ถ้าตัดแกนให้เริ่มที่ 90 แท่งที่ค่า 100 กับ 95 จะดูต่างกันเท่าตัวทั้งที่จริงต่างกันแค่ 5%

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

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

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

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

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

คอลัมน์ทำหน้าที่ชนิดเข้ารหัสด้วยจำนวนค่าที่เหมาะหมายเหตุ
categoryหมวดที่ต้องการเทียบหมวดหมู่x2–12 หมวดถ้าเกิน 12 หมวด ให้รวมตัวเล็กเป็น "อื่น ๆ" หรือเปลี่ยนไปใช้แท่งแนวนอน
valueปริมาณตัวเลขต่อเนื่องyต่อเนื่องต้องเป็นค่าที่บวกกันได้และมีศูนย์ที่มีความหมาย ไม่ใช่ค่าดัชนีหรืออุณหภูมิ

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

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

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

สเกลของแกน — แกนค่าใช้ linear เท่านั้น ห้ามใช้ log เพราะความยาวของแท่งจะไม่แปรตามค่าอีกต่อไป ถ้าข้อมูลกินหลาย order of magnitude ให้ใช้ dot-plot บนสเกล log แทน

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

เกิน 15 หมวด แท่งจะบางจนป้ายชนกัน — เปลี่ยนไปใช้ horizontal-bar หรือ lollipop-chart

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

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

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

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

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

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

  • ไม่บอกว่าแต่ละหมวดเปลี่ยนแปลงอย่างไรตามเวลา ต้องใช้กราฟเส้นหรือ small multiples
  • ไม่บอกการกระจายภายในหมวด — แท่งเดียวอาจมาจากค่าที่กระจุกหรือกระจายมากก็ได้
  • ไม่บอกว่าความต่างที่เห็นมีนัยสำคัญทางสถิติหรือเป็นแค่ความบังเอิญ ต้องใช้ bar-with-error

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

  1. ดูแท่งที่ยาวที่สุดก่อน
  2. ดูช่องว่างระหว่างแท่งแรกกับแท่งถัดไป
  3. กวาดสายตาลงไปหาจุดที่ความยาวเริ่มลดฮวบ
  4. ตรวจว่าแกนเริ่มที่ศูนย์จริง

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

  • หมวดไหนมากที่สุด
  • อันดับหนึ่งนำอันดับสองอยู่เท่าไร
  • หมวดนี้อยู่อันดับที่เท่าไรเมื่อเทียบกับทั้งหมด

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

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

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

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

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

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

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

<หมวดอันดับ 1> นำ <หมวดอันดับ 2> อยู่ <ส่วนต่าง> <หน่วย>

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

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

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

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

d = df.sort_values("value", ascending=False).head(LIMIT)
bars = ax.bar(d["category"], d["value"], color=C1, width=0.72)
bars[0].set_color("#eb6834")          # เน้นแท่งที่จะพูดถึง แท่งอื่นเป็นสีเดียวกันหมด
ax.bar_label(bars, fmt="%.0f", padding=3, fontsize=9, color=INK)
ax.set_ylim(0, None)                   # เริ่มที่ศูนย์เสมอ ห้ามตัดแกน
ax.set_ylabel("ยอดขาย (ล้านบาท)")
ax.set_title("ยอดขายรายจังหวัด", loc="left")
ax.grid(axis="y", alpha=0.25); ax.set_axisbelow(True)
plt.setp(ax.get_xticklabels(), rotation=35, ha="right")

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

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

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

ข้อมูลตัวอย่าง · 10 แถว · seed 42● คำนวณใหม่ในเบราว์เซอร์ทันทีที่ปรับค่า
เปลี่ยนลำดับของแท่ง
ตัดให้เหลือเฉพาะหมวดแรก ๆ
สลับเพื่อเห็นว่าการตัดแกนบิดภาพอย่างไร
0.00100200300400500กรุงเทพฯชลบุรีขอนแก่นเชียงใหม่ภูเก็ตสงขลานครราชสีมาสุราษฎร์ธานีอุดรธานีพิษณุโลกกรุงเทพฯ · 434ชลบุรี · 396ขอนแก่น · 389เชียงใหม่ · 387ภูเก็ต · 351สงขลา · 295นครราชสีมา · 276สุราษฎร์ธานี · 207อุดรธานี · 199พิษณุโลก · 148434
สูงสุดกรุงเทพฯ · 434
จำนวนหมวด10
ผลต่างสูงสุด–ต่ำสุด286
ดูข้อมูลเป็นตาราง (10 แถว)
กราฟแท่งเปรียบเทียบ 10 หมวด สูงสุดคือ กรุงเทพฯ ที่ 434
หมวดค่า
กรุงเทพฯ434
ชลบุรี396
ขอนแก่น389
เชียงใหม่387
ภูเก็ต351
สงขลา295
นครราชสีมา276
สุราษฎร์ธานี207
อุดรธานี199
พิษณุโลก148

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

  • การเรียงลำดับ: ลองสลับไปมาแล้วสังเกตว่า "ตามตัวอักษร" ทำให้หาอันดับได้ยากขึ้นแค่ไหน ทั้งที่ข้อมูลไม่เปลี่ยนเลย
  • จำนวนหมวดที่แสดง: ลดเหลือ 3–5 หมวดแล้วดูว่าภาพอ่านง่ายขึ้นมาก แต่ก็ซ่อนหางยาวของข้อมูลไปด้วย
  • เริ่มแกนที่ศูนย์: ปิดการเริ่มที่ศูนย์แล้วดูว่าความต่างที่แท้จริงเพียงไม่กี่เปอร์เซ็นต์ กลายเป็นภาพที่ดูต่างกันหลายเท่า

ข้อควรระวัง

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

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

  • หมวดมีมากกว่า 15 หมวดใช้แทน: horizontal-bar หรือ lollipop-chart ที่ชื่ออ่านง่ายกว่า
  • แกนนอนเป็นค่าต่อเนื่องไม่ใช่หมวดหมู่ใช้แทน: histogram ซึ่งแท่งต้องชิดกัน
  • ต้องการดูการเปลี่ยนแปลงตามเวลาใช้แทน: line-chart ที่แสดงความชันได้
  • ต้องการดูการกระจายภายในแต่ละกลุ่มใช้แทน: box-plot หรือ strip-plot

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

เทคนิคถัดไป · กราฟแท่งแนวนอน