01ภาพรวมของกราฟนี้
Dendrogram แสดงผลการจัดกลุ่มแบบลำดับชั้น โดยความสูงที่สองกลุ่มมาบรรจบกันบอกว่าทั้งสองต่างกันแค่ไหน สิ่งที่ทำให้มันมีค่ากว่าการบอกแค่ว่ามีกี่กลุ่มคือ มันแสดงโครงสร้างทั้งหมดให้เลือกจุดตัดเองได้
เปรียบเทียบให้เห็นภาพ
เหมือนแผนภูมิวงศ์ตระกูลที่บรรพบุรุษร่วมกันอยู่สูงขึ้นไป ญาติสนิทมาบรรจบกันที่ระดับต่ำ ส่วนญาติห่างต้องขึ้นไปสูงมากกว่าจะเจอบรรพบุรุษร่วม
ใช้ที่ไหนบ้าง — จัดกลุ่มลูกค้าตามพฤติกรรม จัดกลุ่มสินค้าตามคุณสมบัติ วิเคราะห์ความคล้ายของยีน หรือจัดเรียงแถวของ heatmap
สร้างอย่างไร
- ขั้นที่ 1คำนวณระยะห่างระหว่างทุกคู่
- ขั้นที่ 2รวมคู่ที่ใกล้ที่สุดเข้าด้วยกันทีละคู่
- ขั้นที่ 3บันทึกระยะที่รวมกันในแต่ละครั้ง
- ขั้นที่ 4วาดเป็นต้นไม้ที่ความสูงคือระยะที่รวม
ตัวอย่างคลาสสิก · Dendrogram คู่กับ heatmap ในงานชีวสารสนเทศ
รูปแบบมาตรฐานของการวิเคราะห์การแสดงออกของยีนคือวาง heatmap ไว้ตรงกลางและมี dendrogram ที่ขอบทั้งสองด้าน ซึ่งทำหน้าที่สองอย่างพร้อมกัน คือจัดเรียงแถวและคอลัมน์ให้ตัวที่คล้ายกันอยู่ติดกัน และแสดงโครงสร้างของความคล้ายไปด้วย
02อธิบายภาษาคนเข้าใจง่าย ๆ
การจัดกลุ่มส่วนใหญ่บังคับให้เราเลือกจำนวนกลุ่มก่อน แล้วอัลกอริทึมค่อยแบ่งให้ ปัญหาคือเรามักไม่รู้ว่าควรมีกี่กลุ่มตั้งแต่แรก
การจัดกลุ่มแบบลำดับชั้นทำกลับกัน มันเริ่มจากให้ทุกอย่างเป็นกลุ่มของตัวเอง แล้วค่อย ๆ รวมคู่ที่ใกล้ที่สุดเข้าด้วยกันทีละคู่จนเหลือกลุ่มเดียว
Dendrogram บันทึกกระบวนการนั้นทั้งหมด ความสูงที่สองกลุ่มมาบรรจบกันคือระยะห่างระหว่างสองกลุ่มนั้น ยิ่งบรรจบกันต่ำแปลว่ายิ่งคล้ายกัน
ประโยชน์ที่ตามมาคือเราเลือกจำนวนกลุ่มทีหลังได้ โดยลากเส้นแนวนอนตัดที่ความสูงหนึ่ง จำนวนกิ่งที่ถูกตัดคือจำนวนกลุ่มที่ได้
สิ่งที่ควรมองหาคือช่องว่างแนวตั้งที่กว้าง ถ้ามีช่วงความสูงที่ไม่มีการรวมเกิดขึ้นเลย นั่นคือจุดตัดที่ธรรมชาติที่สุด เพราะแปลว่ากลุ่มด้านล่างแน่นและกลุ่มด้านบนห่างกันมาก
03ข้อมูลที่ต้องใช้
คอลัมน์ที่ต้องเตรียม
| คอลัมน์ | ทำหน้าที่ | ชนิด | เข้ารหัสด้วย | จำนวนค่าที่เหมาะ | หมายเหตุ |
|---|---|---|---|---|---|
item | ชื่อรายการ | หมวดหมู่ | x | 5–50 รายการ | จะกลายเป็นใบของต้นไม้ |
ราคา | ตัวแปรที่ใช้วัดความคล้าย | ตัวเลขต่อเนื่อง | y | ต่อเนื่อง | ★ ต้องปรับมาตรฐานก่อน ไม่อย่างนั้นตัวแปรหน่วยใหญ่จะครองระยะทางทั้งหมด |
ต้องเตรียมข้อมูลอย่างไรก่อนวาด
- ★ ปรับมาตรฐานทุกตัวแปรก่อนคำนวณระยะทาง
- เลือกวิธีวัดระยะและวิธีเชื่อมกลุ่มแล้วบันทึกไว้
- ตัดแถวที่ไม่ครบ
ค่าที่หายไป — แถวที่ขาดค่าใดค่าหนึ่งคำนวณระยะทางไม่ได้ ต้องตัดออกและรายงาน
สเกลของแกน — แกนความสูงคือระยะห่าง ซึ่งหน่วยขึ้นกับวิธีวัดที่เลือก จึงต้องระบุวิธีไว้เสมอ
กราฟจะเริ่มพังเมื่อไร
เกิน 60 ใบ ชื่อที่ฐานจะชนกันจนอ่านไม่ได้
หน้าตาไฟล์ที่ต้องเตรียม
item,group,ราคา,ความเร็ว,ความจุ,น้ำหนัก,คะแนนรีวิว
รุ่น A,รุ่นประหยัด,167,48.5,17.6,30.9,3.17
รุ่น B,รุ่นมาตรฐาน,301,55.7,30.4,20,4.09
…04อ่านแล้วเห็นอะไร
สิ่งที่เห็นได้จากภาพ
- คู่ที่คล้ายกันที่สุดจากจุดที่บรรจบกันต่ำที่สุด
- ช่องว่างแนวตั้งที่กว้างซึ่งเป็นจุดตัดที่ธรรมชาติ
- รายการที่รวมเข้ากลุ่มช้าที่สุดซึ่งคือตัวที่แปลกที่สุด
สิ่งที่กราฟนี้ตอบไม่ได้
- ★ ไม่บอกว่าจำนวนกลุ่มที่ถูกต้องคือเท่าไร การเลือกจุดตัดเป็นการตัดสินของคน ไม่ใช่ของข้อมูล
- ผลเปลี่ยนไปตามวิธีวัดระยะและวิธีเชื่อมกลุ่มที่เลือก
อ่านตามลำดับนี้
- มองหาช่องว่างแนวตั้งที่กว้างที่สุด
- ลากเส้นแนวนอนตัดที่ความสูงนั้นแล้วนับกิ่ง
- ดูว่ารายการที่สนใจไปรวมกับใครก่อน
คำถามที่ตอบได้
- ควรแบ่งเป็นกี่กลุ่ม
- รายการนี้คล้ายกับรายการไหนที่สุด
- มีรายการไหนที่ไม่เข้าพวกเลย
สัญญาณว่ามีอะไรผิด
- ไม่ระบุวิธีวัดระยะและวิธีเชื่อมกลุ่ม ซึ่งเปลี่ยนผลได้มาก
- ไม่ได้ปรับมาตรฐานตัวแปรก่อน
05เหมาะกับการนำเสนอแบบไหน
ทำอย่างไรให้คนอ่านได้ข้อสรุปโดยไม่ต้องบรรยาย
- ระบุวิธีวัดระยะและวิธีเชื่อมกลุ่มไว้ในคำอธิบาย
- ลากเส้นแนวนอนของจุดตัดที่เลือกพร้อมบอกว่าได้กี่กลุ่ม
- ระบายสีกิ่งตามกลุ่มที่ได้หลังตัด
รูปแบบชื่อกราฟที่ควรใช้
ที่ระยะ <ค่า> ข้อมูลแบ่งเป็น <จำนวน> กลุ่มที่ชัดเจน
06เอาไปใช้ต่อ
โค้ดทุกชิ้นอ่านไฟล์ dendrogram-sample.csv ชุดเดียวกับที่ Playground ใช้ และตัวเลขในโค้ดเปลี่ยนตามค่าที่คุณปรับด้านล่าง
# ติดตั้ง: pip install "matplotlib==3.10.*" "pandas==2.*"
# ดาวน์โหลด dendrogram-sample.csv จากหน้านี้ แล้ววางไว้ข้างสคริปต์
import matplotlib
matplotlib.use("Agg") # รันแบบไม่มีหน้าจอ ถ้ารันในเครื่องตัวเองลบบรรทัดนี้ได้
import matplotlib.pyplot as plt
import pandas as pd
from scipy.cluster.hierarchy import dendrogram, linkage
from sklearn.preprocessing import StandardScaler
C1, C2, C3 = "#2a78d6", "#eb6834", "#1baf7a" # palette ของคลัง เปลี่ยนเป็นสีองค์กรได้
INK, SURFACE = "#0b0b0b", "#fcfcfb"
df = pd.read_csv("dendrogram-sample.csv")
df["ราคา"] = pd.to_numeric(df["ราคา"], errors="coerce")
df["ความเร็ว"] = pd.to_numeric(df["ความเร็ว"], errors="coerce")
df["ความจุ"] = pd.to_numeric(df["ความจุ"], errors="coerce")
df["น้ำหนัก"] = pd.to_numeric(df["น้ำหนัก"], errors="coerce")
df["คะแนนรีวิว"] = pd.to_numeric(df["คะแนนรีวิว"], errors="coerce")
NOTE = "gap" # ← ค่าจาก Playground
fig, ax = plt.subplots(figsize=(7.6, 4.2), facecolor=SURFACE)
ax.set_facecolor(SURFACE)
cols = ["ราคา", "ความเร็ว", "ความจุ", "น้ำหนัก", "คะแนนรีวิว"]
X = StandardScaler().fit_transform(df[cols]) # ★ ปรับมาตรฐานก่อนเสมอ
Z = linkage(X, method="ward", metric="euclidean") # ต้องระบุวิธีทั้งสองในคำอธิบายภาพ
dendrogram(Z, labels=list(df["item"]), ax=ax, color_threshold=0.7 * max(Z[:, 2]),
leaf_font_size=8)
ax.set_ylabel("ระยะที่รวมกลุ่ม (ward, euclidean)")
ax.spines[["top", "right"]].set_visible(False)
ax.spines[["top", "right"]].set_visible(False) # ลดเส้นที่ไม่ได้ให้ข้อมูล
fig.tight_layout()
fig.savefig("dendrogram.png", dpi=160)
print("เขียน dendrogram.png แล้ว ·", len(df), "แถว")07ลองเล่นเพื่อเข้าใจ
การเลือกจุดตัดแนวนอนคือคนตัดสิน ไม่ใช่ข้อมูลตัดสิน — จำนวนกลุ่มเปลี่ยนตามความสูงที่เลือก
ดูข้อมูลเป็นตาราง (11 แถว)
| ลำดับการรวม | ระยะ | จำนวนสมาชิกหลังรวม |
|---|---|---|
| 1 | 1.00 | 2 |
| 2 | 2.50 | 3 |
| 3 | 3.00 | 2 |
| 4 | 5.25 | 4 |
| 5 | 6.00 | 2 |
| 6 | 9.00 | 2 |
| 7 | 12.0 | 2 |
| 8 | 20.5 | 4 |
| 9 | 31.5 | 4 |
| 10 | 105 | 8 |
| 11 | 178 | 12 |
ลองแล้วจะเห็นอะไร
- สังเกตอะไร: มองหาช่วงความสูงที่ไม่มีการรวมเกิดขึ้นเลย ลากเส้นตัดตรงนั้นแล้วนับกิ่ง นั่นคือจำนวนกลุ่มที่ข้อมูลบอกเอง
ข้อควรระวัง
- ★ ไม่ปรับมาตรฐานตัวแปรก่อน ทำให้ตัวแปรที่หน่วยใหญ่ครองระยะทางทั้งหมด
- ไม่ระบุวิธีวัดระยะและวิธีเชื่อมกลุ่ม ซึ่งเปลี่ยนผลได้มาก
- เลือกจุดตัดโดยไม่ดูช่องว่างของความสูง แล้วอ้างว่าข้อมูลบอกว่ามีกี่กลุ่ม
- ใส่รายการมากเกินไปจนชื่อที่ฐานชนกัน
เมื่อไหร่ไม่ควรใช้กราฟนี้
- รู้จำนวนกลุ่มอยู่แล้ว→ใช้แทน: scatter-plot ที่ระบายสีตามกลุ่ม
- มีมากกว่า 60 รายการ→ใช้แทน: heatmap-matrix ที่จัดเรียงตามผลการจัดกลุ่ม
- ข้อมูลเป็นลำดับชั้นอยู่แล้วโดยธรรมชาติ→ใช้แทน: node-link-tree