01ภาพรวมของกราฟนี้
Histogram แบ่งช่วงของตัวเลขหนึ่งคอลัมน์ออกเป็นถัง (bin) ที่กว้างเท่ากัน แล้ววาดแท่งสูงตามจำนวนข้อมูลในแต่ละถัง ผลที่ได้คือรูปร่างของการกระจาย ซึ่งบอกอะไรที่ค่าเฉลี่ยกับส่วนเบี่ยงเบนมาตรฐานสองตัวเลขบอกไม่ได้
เปรียบเทียบให้เห็นภาพ
เหมือนเรียงนักเรียนทั้งโรงเรียนตามส่วนสูง แล้วให้คนที่สูงใกล้กันยืนรวมเป็นแถวเดียวกัน แถวไหนคนเยอะแปลว่าช่วงส่วนสูงนั้นพบบ่อย
ใช้ที่ไหนบ้าง — ตรวจว่าข้อมูลเบ้ไปทางไหนก่อนเลือกโมเดล ดูว่าราคาสินค้ากระจุกที่ช่วงไหน หรือหาว่ามีสองกลุ่มปนกันอยู่ในข้อมูลหรือไม่
สร้างอย่างไร
- ขั้นที่ 1เลือกคอลัมน์ตัวเลขหนึ่งคอลัมน์
- ขั้นที่ 2กำหนดจำนวนหรือความกว้างของ bin
- ขั้นที่ 3นับจำนวนข้อมูลในแต่ละ bin
- ขั้นที่ 4วาดแท่งสูงตามจำนวน โดยแท่งชิดกัน
ตัวอย่างคลาสสิก · การกระจายของความสูงมนุษย์ และการค้นพบว่ามันมีสองยอด
เมื่อรวมความสูงของผู้ชายและผู้หญิงไว้ในชุดเดียว histogram จะแสดงสองยอด ซึ่งเป็นตัวอย่างคลาสสิกที่สุดของ "ค่าเฉลี่ยเดียวไม่ได้เล่าความจริง" เพราะค่าเฉลี่ยจะตกอยู่ตรงหุบเขาระหว่างยอดทั้งสอง ซึ่งเป็นค่าที่แทบไม่มีใครมีจริง
02อธิบายภาษาคนเข้าใจง่าย ๆ
สมมติเรามีคะแนนสอบของนักเรียน 500 คน ถ้าบอกแค่ว่าค่าเฉลี่ยคือ 65 คะแนน เรายังไม่รู้เลยว่าเกิดอะไรขึ้นจริง ๆ อาจเป็นว่าเกือบทุกคนได้ราว ๆ 65 หรืออาจเป็นว่าครึ่งหนึ่งได้ 40 อีกครึ่งได้ 90 ซึ่งสองแบบนี้ต้องแก้ปัญหาคนละทางกันโดยสิ้นเชิง
Histogram ตอบคำถามนี้ด้วยวิธีง่ายมาก คือแบ่งช่วงคะแนนเป็นช่วงย่อยที่กว้างเท่ากัน เช่น 0 ถึง 10 ไปจนถึง 90 ถึง 100 แล้วนับว่าแต่ละช่วงมีนักเรียนกี่คน จากนั้นวาดแท่งให้สูงตามจำนวนที่นับได้
สิ่งที่ทำให้ Histogram ต่างจากกราฟแท่งธรรมดาคือแกนนอนของมันเป็นตัวเลขต่อเนื่อง ไม่ใช่หมวดหมู่ แท่งจึงต้องวางชิดกันเพื่อสื่อว่าช่วงค่าต่อเนื่องกันไป ถ้าเว้นช่องว่างระหว่างแท่ง คนอ่านจะเข้าใจผิดว่าเป็นหมวดที่แยกขาดจากกัน
จำนวน bin คือการตัดสินใจที่สำคัญที่สุดและเป็นจุดที่คนพลาดบ่อยที่สุด ถ้า bin น้อยเกินไปรูปร่างจะเรียบจนกลืนรายละเอียดที่สำคัญ เช่น ยอดสองยอดจะรวมเป็นยอดเดียว ถ้า bin มากเกินไปแท่งจะหยักขึ้นลงตามความบังเอิญของข้อมูลจนดูเหมือนมีรูปแบบทั้งที่ไม่มี
วิธีปฏิบัติที่ปลอดภัยคือลองหลายค่าแล้วดูว่าข้อสรุปเปลี่ยนไหม ถ้าเห็นสองยอดที่ bin เท่าไรก็ยังเห็น แปลว่ามีจริง แต่ถ้ายอดที่สองหายไปเมื่อเปลี่ยน bin เล็กน้อย ก็ยังสรุปไม่ได้ Playground ด้านล่างออกแบบมาให้ลองข้อนี้โดยเฉพาะ
03ข้อมูลที่ต้องใช้
คอลัมน์ที่ต้องเตรียม
| คอลัมน์ | ทำหน้าที่ | ชนิด | เข้ารหัสด้วย | จำนวนค่าที่เหมาะ | หมายเหตุ |
|---|---|---|---|---|---|
value | ค่าที่ต้องการดูการกระจาย | ตัวเลขต่อเนื่อง | x | ต่อเนื่อง | ★ ต้องเป็นข้อมูลดิบรายแถว ห้ามสรุปมาก่อน — ถ้ามีแต่ค่าเฉลี่ยแล้ว วาด histogram ไม่ได้ |
ต้องเตรียมข้อมูลอย่างไรก่อนวาด
- กรองค่าหายออก และบันทึกไว้ว่ากรองไปกี่แถว
- ตัดสินใจเรื่องค่าผิดปกติก่อนวาด: จะคงไว้ จะตัด หรือจะใช้ scale log
- ถ้าข้อมูลเบ้ขวาแรง พิจารณา log-transform แล้วบอกในชื่อแกนว่าทำแล้ว
ค่าที่หายไป — ตัดแถวที่ค่าว่างออกจากการนับ และเขียนจำนวนที่ตัดไว้ใน caption เสมอ — ถ้าค่าหายไม่ได้สุ่ม การกระจายที่เห็นจะบิด
สเกลของแกน — แกน x ใช้ linear ตามค่าจริง ถ้าข้อมูลเบ้ขวาแรง เช่น รายได้ ใช้ log บนแกน x และคง bin ให้กว้างเท่ากันในสเกล log
กราฟจะเริ่มพังเมื่อไร
ต่ำกว่า 30 แถว รูปร่างจะเป็นผลของความบังเอิญมากกว่าของจริง — ใช้ strip-plot หรือ dot-plot แทน
หน้าตาไฟล์ที่ต้องเตรียม
value
…04อ่านแล้วเห็นอะไร
สิ่งที่เห็นได้จากภาพ
- ข้อมูลกระจุกอยู่ช่วงไหนมากที่สุด
- การกระจายมียอดเดียวหรือหลายยอด — หลายยอดมักแปลว่ามีหลายกลุ่มปนกันอยู่
- เบ้ไปทางไหน — หางยาวทางขวาแปลว่ามีค่าสูงผิดปกติจำนวนน้อย
- ช่วงที่ไม่มีข้อมูลเลย ซึ่งมักเป็นสัญญาณของการปัดค่าหรือการตัดข้อมูล
สิ่งที่กราฟนี้ตอบไม่ได้
- บอกไม่ได้ว่าแต่ละแถวเป็นของใคร — ข้อมูลรายตัวหายไปหมดหลังนับรวม
- เทียบสองกลุ่มโดยตรงไม่ได้ถ้าซ้อนกันบนภาพเดียว ให้ใช้ box-plot หรือ small-multiples แทน
- ไม่บอกลำดับเวลา แม้ข้อมูลจะเก็บมาตามเวลาก็ตาม
อ่านตามลำดับนี้
- ดูตำแหน่งยอดก่อน — ข้อมูลส่วนใหญ่อยู่ตรงไหน
- ดูความกว้าง — แคบแปลว่าค่าใกล้เคียงกัน กว้างแปลว่ากระจาย
- ดูความสมมาตร — หางข้างไหนยาวกว่า
- ดูจำนวนยอด — มากกว่าหนึ่งยอดแปลว่าควรแยกวิเคราะห์
คำถามที่ตอบได้
- ค่าส่วนใหญ่ตกอยู่ในช่วงไหน
- ข้อมูลชุดนี้มีแค่กลุ่มเดียวหรือหลายกลุ่ม
- ใช้ค่าเฉลี่ยเป็นตัวแทนได้ไหม หรือควรใช้มัธยฐาน
สัญญาณว่ามีอะไรผิด
- แท่งสูงผิดปกติที่ค่ากลม ๆ เช่น 0, 50, 100 มักเป็นค่าที่คนกรอกมั่วหรือค่า default
- แท่งเดียวสูงลิ่วที่ขอบขวาสุด มักแปลว่าข้อมูลถูก cap ไว้ที่ค่าสูงสุด
- รูปร่างเปลี่ยนไปคนละเรื่องเมื่อขยับจำนวน bin นิดเดียว แปลว่าข้อมูลน้อยเกินกว่าจะสรุป
05เหมาะกับการนำเสนอแบบไหน
ทำอย่างไรให้คนอ่านได้ข้อสรุปโดยไม่ต้องบรรยาย
- ลากเส้นแนวตั้งที่ค่าเฉลี่ยและมัธยฐาน แล้วติดป้ายทั้งสอง — ระยะห่างของสองเส้นนี้บอกความเบ้ทันที
- เขียนจำนวนแถวทั้งหมดและจำนวนที่ถูกตัดออกไว้ใน caption
- ระบุความกว้างของ bin ไว้ใน caption เสมอ เพราะมันเปลี่ยนรูปที่เห็น
รูปแบบชื่อกราฟที่ควรใช้
<ตัวแปร> ของ <ประชากร> กระจุกที่ <ช่วง> และมีหางยาวทาง <ซ้าย/ขวา>
06เอาไปใช้ต่อ
โค้ดทุกชิ้นอ่านไฟล์ histogram-sample.csv ชุดเดียวกับที่ Playground ใช้ และตัวเลขในโค้ดเปลี่ยนตามค่าที่คุณปรับด้านล่าง
# ติดตั้ง: pip install "matplotlib==3.10.*" "pandas==2.*"
# ดาวน์โหลด histogram-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("histogram-sample.csv")
df["value"] = pd.to_numeric(df["value"], errors="coerce")
BINS = 24
SCALE = "linear" # ← ค่าจาก Playground
fig, ax = plt.subplots(figsize=(7.6, 4.2), facecolor=SURFACE)
ax.set_facecolor(SURFACE)
values = df["value"].dropna()
dropped = len(df) - len(values)
ax.hist(values, bins=BINS, color=C1, edgecolor=SURFACE, linewidth=1.2)
ax.axvline(values.mean(), color=INK, linewidth=1.2, linestyle="--") # ค่าเฉลี่ย
ax.axvline(values.median(), color=INK, linewidth=1.2) # มัธยฐาน
ax.set_xlabel("ค่าที่วัดได้"); ax.set_ylabel("จำนวนข้อมูล")
ax.set_title(f"การกระจาย · {BINS} bin · n={len(values)} (ตัดค่าว่าง {dropped} แถว)", loc="left")
ax.grid(axis="y", alpha=0.25); ax.set_axisbelow(True)
ax.spines[["top", "right"]].set_visible(False) # ลดเส้นที่ไม่ได้ให้ข้อมูล
fig.tight_layout()
fig.savefig("histogram.png", dpi=160)
print("เขียน histogram.png แล้ว ·", len(df), "แถว")07ลองเล่นเพื่อเข้าใจ
ดูข้อมูลเป็นตาราง (24 แถว)
| ช่วง | จำนวน |
|---|---|
| 43.3–45.1 | 13 |
| 45.1–46.8 | 16 |
| 46.8–48.5 | 41 |
| 48.5–50.3 | 52 |
| 50.3–52.0 | 62 |
| 52.0–53.7 | 58 |
| 53.7–55.5 | 47 |
| 55.5–57.2 | 32 |
| 57.2–58.9 | 29 |
| 58.9–60.6 | 9 |
| 60.6–62.4 | 0 |
| 62.4–64.1 | 1 |
| 64.1–65.8 | 0 |
| 65.8–67.6 | 0 |
| 67.6–69.3 | 0 |
| 69.3–71.0 | 0 |
| 71.0–72.8 | 8 |
| 72.8–74.5 | 16 |
| 74.5–76.2 | 28 |
| 76.2–77.9 | 50 |
| 77.9–79.7 | 61 |
| 79.7–81.4 | 39 |
| 81.4–83.1 | 28 |
| 83.1–84.9 | 10 |
ลองแล้วจะเห็นอะไร
- จำนวน bin: ลากไปซ้ายสุดจะเห็นยอดเดียว ลากไปขวาสุดจะเห็นแท่งหยักเป็นฟันปลา — ข้อมูลชุดนี้มีสองยอดจริง และจะเห็นชัดที่สุดราว 20 ถึง 30 bin
- สเกลแกน x: กับข้อมูลที่เบ้ขวา การใช้ log ทำให้เห็นโครงสร้างที่ linear บีบจนแบน
ข้อควรระวัง
- ใช้จำนวน bin ค่า default ของไลบรารีแล้วสรุปเลย — ต้องลองหลายค่าเสมอก่อนสรุปรูปร่าง
- เว้นช่องว่างระหว่างแท่ง ทำให้ดูเหมือนกราฟแท่งหมวดหมู่ ทั้งที่แกนเป็นค่าต่อเนื่อง
- เอา histogram ของสองกลุ่มมาซ้อนทับกันจนอ่านไม่ออก — ใช้ small multiples หรือ density แทน
- แกนตั้งไม่เริ่มที่ศูนย์ ทำให้สัดส่วนความสูงโกหก
- วาด histogram จากข้อมูลที่สรุปมาแล้ว เช่น ค่าเฉลี่ยรายจังหวัด ทั้งที่ควรใช้ข้อมูลดิบ
- ไม่บอกว่าตัดค่าผิดปกติออกไปแล้ว ทำให้คนอ่านเห็นการกระจายที่ไม่ตรงความจริง
เมื่อไหร่ไม่ควรใช้กราฟนี้
- ข้อมูลน้อยกว่า 30 แถว→ใช้แทน: strip-plot หรือ dot-plot ที่แสดงทุกจุดจริง
- ต้องเทียบการกระจายมากกว่า 3 กลุ่ม→ใช้แทน: box-plot หรือ ridgeline-plot
- ตัวแปรเป็นหมวดหมู่ไม่ใช่ตัวเลขต่อเนื่อง→ใช้แทน: bar-chart
- ต้องการอ่านว่าสัดส่วนเท่าไรที่ต่ำกว่าค่าหนึ่ง→ใช้แทน: ecdf-plot ซึ่งอ่านค่านั้นได้ตรง ๆ