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

กราฟการจัดกลุ่มDendrogram

ดูว่าอะไรคล้ายอะไร และคล้ายแค่ไหน

4
ขั้นสูงควรรู้ก่อน · เข้าใจแนวคิดระยะห่างและการจัดกลุ่ม
ลองเล่น

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

Dendrogram แสดงผลการจัดกลุ่มแบบลำดับชั้น โดยความสูงที่สองกลุ่มมาบรรจบกันบอกว่าทั้งสองต่างกันแค่ไหน สิ่งที่ทำให้มันมีค่ากว่าการบอกแค่ว่ามีกี่กลุ่มคือ มันแสดงโครงสร้างทั้งหมดให้เลือกจุดตัดเองได้

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

เหมือนแผนภูมิวงศ์ตระกูลที่บรรพบุรุษร่วมกันอยู่สูงขึ้นไป ญาติสนิทมาบรรจบกันที่ระดับต่ำ ส่วนญาติห่างต้องขึ้นไปสูงมากกว่าจะเจอบรรพบุรุษร่วม

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

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

  1. ขั้นที่ 1คำนวณระยะห่างระหว่างทุกคู่
  2. ขั้นที่ 2รวมคู่ที่ใกล้ที่สุดเข้าด้วยกันทีละคู่
  3. ขั้นที่ 3บันทึกระยะที่รวมกันในแต่ละครั้ง
  4. ขั้นที่ 4วาดเป็นต้นไม้ที่ความสูงคือระยะที่รวม

ตัวอย่างคลาสสิก · Dendrogram คู่กับ heatmap ในงานชีวสารสนเทศ

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

Wikipedia · Dendrogram

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

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

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

Dendrogram บันทึกกระบวนการนั้นทั้งหมด ความสูงที่สองกลุ่มมาบรรจบกันคือระยะห่างระหว่างสองกลุ่มนั้น ยิ่งบรรจบกันต่ำแปลว่ายิ่งคล้ายกัน

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

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

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

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

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

คอลัมน์ทำหน้าที่ชนิดเข้ารหัสด้วยจำนวนค่าที่เหมาะหมายเหตุ
itemชื่อรายการหมวดหมู่x5–50 รายการจะกลายเป็นใบของต้นไม้
ราคาตัวแปรที่ใช้วัดความคล้ายตัวเลขต่อเนื่องyต่อเนื่อง★ ต้องปรับมาตรฐานก่อน ไม่อย่างนั้นตัวแปรหน่วยใหญ่จะครองระยะทางทั้งหมด

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

  1. ★ ปรับมาตรฐานทุกตัวแปรก่อนคำนวณระยะทาง
  2. เลือกวิธีวัดระยะและวิธีเชื่อมกลุ่มแล้วบันทึกไว้
  3. ตัดแถวที่ไม่ครบ

ค่าที่หายไป — แถวที่ขาดค่าใดค่าหนึ่งคำนวณระยะทางไม่ได้ ต้องตัดออกและรายงาน

สเกลของแกน — แกนความสูงคือระยะห่าง ซึ่งหน่วยขึ้นกับวิธีวัดที่เลือก จึงต้องระบุวิธีไว้เสมอ

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

เกิน 60 ใบ ชื่อที่ฐานจะชนกันจนอ่านไม่ได้

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

item,group,ราคา,ความเร็ว,ความจุ,น้ำหนัก,คะแนนรีวิว
รุ่น A,รุ่นประหยัด,167,48.5,17.6,30.9,3.17
รุ่น B,รุ่นมาตรฐาน,301,55.7,30.4,20,4.09

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

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

  • คู่ที่คล้ายกันที่สุดจากจุดที่บรรจบกันต่ำที่สุด
  • ช่องว่างแนวตั้งที่กว้างซึ่งเป็นจุดตัดที่ธรรมชาติ
  • รายการที่รวมเข้ากลุ่มช้าที่สุดซึ่งคือตัวที่แปลกที่สุด

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

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

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

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

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

  • ควรแบ่งเป็นกี่กลุ่ม
  • รายการนี้คล้ายกับรายการไหนที่สุด
  • มีรายการไหนที่ไม่เข้าพวกเลย

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

  • ไม่ระบุวิธีวัดระยะและวิธีเชื่อมกลุ่ม ซึ่งเปลี่ยนผลได้มาก
  • ไม่ได้ปรับมาตรฐานตัวแปรก่อน

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

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

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

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

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

ที่ระยะ <ค่า> ข้อมูลแบ่งเป็น <จำนวน> กลุ่มที่ชัดเจน

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), "แถว")

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

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

ข้อมูลตัวอย่าง · 12 แถว · seed 197● คำนวณใหม่ในเบราว์เซอร์ทันทีที่ปรับค่า
ช่องว่างกว้างคือจุดตัดที่ธรรมชาติ
ระยะ 1.00ระยะ 2.50ระยะ 3.00ระยะ 5.25ระยะ 6.00ระยะ 9.00ระยะ 12.0ระยะ 20.5ระยะ 31.5ระยะ 105ระยะ 178รุ่น Aรุ่น Bรุ่น Cรุ่น Dรุ่น Eรุ่น Fรุ่น Gรุ่น Hรุ่น Iรุ่น Jรุ่น Kรุ่น Lระยะที่รวม

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

จำนวนรายการ12
ระยะที่รวมครั้งสุดท้าย178
ช่องว่างที่ใหญ่ที่สุด73.4
ดูข้อมูลเป็นตาราง (11 แถว)
dendrogram 12 รายการ
ลำดับการรวมระยะจำนวนสมาชิกหลังรวม
11.002
22.503
33.002
45.254
56.002
69.002
712.02
820.54
931.54
101058
1117812

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

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

ข้อควรระวัง

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

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

  • รู้จำนวนกลุ่มอยู่แล้วใช้แทน: scatter-plot ที่ระบายสีตามกลุ่ม
  • มีมากกว่า 60 รายการใช้แทน: heatmap-matrix ที่จัดเรียงตามผลการจัดกลุ่ม
  • ข้อมูลเป็นลำดับชั้นอยู่แล้วโดยธรรมชาติใช้แทน: node-link-tree

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

เทคนิคถัดไป · ต้นไม้รัศมี