01ภาพรวมของกราฟนี้
Adjacency matrix วางโหนดทั้งแถวและคอลัมน์แล้วระบายช่องที่มีการเชื่อมต่อ ข้อดีที่ชัดเจนคือไม่มีเส้นทับกันเลยไม่ว่าเครือข่ายจะหนาแน่นแค่ไหน แลกกับการที่เส้นทางหลายขั้นซึ่งเป็นจุดแข็งของกราฟแบบเส้นกลับอ่านแทบไม่ได้
เปรียบเทียบให้เห็นภาพ
เหมือนตารางระยะทางระหว่างเมืองในแผนที่พับ ซึ่งอ่านคู่ใดคู่หนึ่งได้ทันทีแต่บอกเส้นทางขับรถจริงไม่ได้
ใช้ที่ไหนบ้าง — เครือข่ายหนาแน่นที่กราฟแบบเส้นอ่านไม่ได้ เมทริกซ์การค้าระหว่างประเทศ หรือการเรียกใช้ระหว่างบริการในระบบ
สร้างอย่างไร
- ขั้นที่ 1สร้างตารางที่แถวและคอลัมน์เป็นโหนดชุดเดียวกัน
- ขั้นที่ 2ระบายช่องด้วยน้ำหนักการเชื่อมต่อ
- ขั้นที่ 3เรียงลำดับโหนดด้วยอัลกอริทึมจัดกลุ่ม
- ขั้นที่ 4ทำเครื่องหมายเส้นทแยงมุมให้ชัด
ตัวอย่างคลาสสิก · เมทริกซ์การเรียกใช้ระหว่างบริการในระบบไมโครเซอร์วิส
ระบบที่มีบริการหลายสิบตัววาดเป็นกราฟแบบเส้นแล้วกลายเป็นก้อนขนแมวทันที เมื่อเปลี่ยนเป็นเมทริกซ์และเรียงด้วยอัลกอริทึมจัดกลุ่ม บล็อกสี่เหลี่ยมที่ปรากฏขึ้นก็เผยขอบเขตของระบบย่อยที่แท้จริง ซึ่งมักไม่ตรงกับผังที่ทีมเขียนไว้
02อธิบายภาษาคนเข้าใจง่าย ๆ
ปัญหาใหญ่ที่สุดของกราฟแบบเส้นคือเมื่อเส้นเชื่อมเยอะ เส้นจะทับกันจนกลายเป็นก้อนขนแมวที่ไม่บอกอะไรเลย
Adjacency matrix แก้ที่รากของปัญหา ด้วยการเลิกใช้เส้นทั้งหมด แล้วเปลี่ยนแต่ละความสัมพันธ์เป็นช่องหนึ่งช่องในตาราง
ผลคือไม่ว่าเครือข่ายจะหนาแน่นแค่ไหน ภาพก็ยังอ่านได้เท่าเดิม เพราะช่องไม่มีทางทับกัน ซึ่งเป็นข้อได้เปรียบที่เด็ดขาดกับเครือข่ายใหญ่
ราคาที่จ่ายอย่างแรกคือเส้นทางหลายขั้นหายไป การถามว่า A ไป C ผ่าน B ได้ไหมนั้นดูจากกราฟแบบเส้นใช้เวลาวินาทีเดียว แต่ในเมทริกซ์ต้องไล่สองช่องแยกกัน
อย่างที่สองคือการเรียงลำดับสำคัญมากจนเปลี่ยนข้อสรุป เรียงตามตัวอักษรจะเห็นแค่จุดกระจาย แต่เรียงด้วยอัลกอริทึมจัดกลุ่มจะเห็นบล็อกสี่เหลี่ยมที่คือกลุ่มย่อยชัดเจน
03ข้อมูลที่ต้องใช้
คอลัมน์ที่ต้องเตรียม
| คอลัมน์ | ทำหน้าที่ | ชนิด | เข้ารหัสด้วย | จำนวนค่าที่เหมาะ | หมายเหตุ |
|---|---|---|---|---|---|
source | โหนดแถว | โหนด | row | 10–200 โหนด | รองรับโหนดได้มากกว่ากราฟแบบเส้นมาก |
target | โหนดคอลัมน์ | โหนด | column | ชุดเดียวกับ source | ต้องใช้ชุดและลำดับเดียวกันทั้งสองแกน |
value | น้ำหนักการเชื่อมต่อ | ตัวเลขต่อเนื่อง | color | ศูนย์ถึงสูงสุด | ช่องว่างแปลว่าไม่มีการเชื่อมต่อ |
ต้องเตรียมข้อมูลอย่างไรก่อนวาด
- ★ เรียงโหนดด้วยอัลกอริทึมจัดกลุ่ม ไม่ใช่ตามตัวอักษร
- ใช้ลำดับเดียวกันทั้งสองแกน
- ตัดสินใจว่าเมทริกซ์สมมาตรหรือมีทิศทาง
ค่าที่หายไป — ช่องที่ไม่มีข้อมูลต้องแยกจากช่องที่มีค่าศูนย์ด้วยพื้นหลังต่างกัน
สเกลของแกน — ใช้สเกลสีลำดับเดียวไล่อ่อนไปเข้ม และแสดงช่วงค่าในคำอธิบายสีเสมอ
กราฟจะเริ่มพังเมื่อไร
เกิน 200 โหนด ช่องเล็กจนกดไม่ได้และชื่อแกนอ่านไม่ออก
หน้าตาไฟล์ที่ต้องเตรียม
source,target,value
เข้าชมเว็บ,ดูสินค้า,7975
เข้าชมเว็บ,ออกทันที,4078
…04อ่านแล้วเห็นอะไร
สิ่งที่เห็นได้จากภาพ
- บล็อกสี่เหลี่ยมทึบซึ่งคือกลุ่มที่เชื่อมกันครบทุกคู่
- แถวหรือคอลัมน์ที่เข้มทั้งแนวซึ่งคือโหนดศูนย์กลาง
- ความสมมาตรหรือไม่สมมาตรของความสัมพันธ์
สิ่งที่กราฟนี้ตอบไม่ได้
- ★ เส้นทางหลายขั้นอ่านแทบไม่ได้ ซึ่งเป็นสิ่งที่กราฟแบบเส้นทำได้ทันที
- โครงสร้างภาพรวมของเครือข่ายเห็นยากกว่ากราฟแบบเส้น
อ่านตามลำดับนี้
- มองหาบล็อกทึบตามแนวเส้นทแยงมุมซึ่งคือกลุ่มย่อย
- ดูแถวที่เข้มทั้งแนวซึ่งคือโหนดที่เชื่อมกับทุกคน
- เทียบครึ่งบนกับครึ่งล่างเพื่อดูความสมมาตร
คำถามที่ตอบได้
- A กับ B เชื่อมกันไหมและแรงแค่ไหน
- มีกลุ่มที่เชื่อมกันครบทุกคู่ไหม
- โหนดไหนเชื่อมกับคนอื่นมากที่สุด
สัญญาณว่ามีอะไรผิด
- เรียงตามตัวอักษรแทนการจัดกลุ่ม ทำให้บล็อกกระจายจนมองไม่เห็น
- ใช้สเกลสีหลายสีแทนสเกลลำดับเดียว
- ไม่แยกช่องที่ไม่มีข้อมูลจากช่องที่เป็นศูนย์
05เหมาะกับการนำเสนอแบบไหน
ทำอย่างไรให้คนอ่านได้ข้อสรุปโดยไม่ต้องบรรยาย
- เขียนกำกับว่าเรียงลำดับด้วยวิธีใด
- ตีกรอบบล็อกที่คือกลุ่มย่อยเพื่อชี้ให้เห็น
- ทำเส้นทแยงมุมให้ต่างจากช่องอื่นชัดเจน
รูปแบบชื่อกราฟที่ควรใช้
เครือข่าย <จำนวน> โหนด โดยเห็นกลุ่มที่เชื่อมกันแน่น <จำนวน> กลุ่ม
06เอาไปใช้ต่อ
โค้ดทุกชิ้นอ่านไฟล์ adjacency-matrix-sample.csv ชุดเดียวกับที่ Playground ใช้ และตัวเลขในโค้ดเปลี่ยนตามค่าที่คุณปรับด้านล่าง
# ติดตั้ง: pip install "matplotlib==3.10.*" "pandas==2.*"
# ดาวน์โหลด adjacency-matrix-sample.csv จากหน้านี้ แล้ววางไว้ข้างสคริปต์
import matplotlib
matplotlib.use("Agg") # รันแบบไม่มีหน้าจอ ถ้ารันในเครื่องตัวเองลบบรรทัดนี้ได้
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from scipy.cluster.hierarchy import leaves_list, linkage
C1, C2, C3 = "#2a78d6", "#eb6834", "#1baf7a" # palette ของคลัง เปลี่ยนเป็นสีองค์กรได้
INK, SURFACE = "#0b0b0b", "#fcfcfb"
df = pd.read_csv("adjacency-matrix-sample.csv")
df["value"] = pd.to_numeric(df["value"], errors="coerce")
NOTE = "block" # ← ค่าจาก Playground
fig, ax = plt.subplots(figsize=(7.6, 4.2), facecolor=SURFACE)
ax.set_facecolor(SURFACE)
mat = df.pivot_table(index="source", columns="target", values="value", aggfunc="sum")
nodes = sorted(set(mat.index) | set(mat.columns))
mat = mat.reindex(index=nodes, columns=nodes).fillna(0)
order = leaves_list(linkage(mat.values, method="average")) # เรียงด้วยการจัดกลุ่ม ไม่ใช่ตัวอักษร
mat = mat.iloc[order, order]
im = ax.imshow(mat.values, cmap="Blues", aspect="equal")
ax.set_xticks(range(len(mat)), mat.columns, rotation=90, fontsize=8)
ax.set_yticks(range(len(mat)), mat.index, fontsize=8)
fig.colorbar(im, ax=ax, label="น้ำหนักการเชื่อมต่อ", shrink=0.8)
ax.spines[["top", "right"]].set_visible(False) # ลดเส้นที่ไม่ได้ให้ข้อมูล
fig.tight_layout()
fig.savefig("adjacency-matrix.png", dpi=160)
print("เขียน adjacency-matrix.png แล้ว ·", len(df), "แถว")07ลองเล่นเพื่อเข้าใจ
ลำดับแถวและคอลัมน์เปลี่ยนสิ่งที่เห็น — ต้องจัดเรียงให้กลุ่มมาอยู่ติดกันก่อน ไม่อย่างนั้นโครงสร้างจะมองไม่ออก
ดูข้อมูลเป็นตาราง (8 แถว)
| จาก | ไป | น้ำหนัก |
|---|---|---|
| เข้าชมเว็บ | ดูสินค้า | 7,975 |
| เข้าชมเว็บ | ออกทันที | 4,078 |
| ดูสินค้า | ใส่ตะกร้า | 3,083 |
| ดูสินค้า | ออกกลางทาง | 5,112 |
| ใส่ตะกร้า | กรอกที่อยู่ | 1,952 |
| ใส่ตะกร้า | ทิ้งตะกร้า | 1,166 |
| กรอกที่อยู่ | ชำระเงินสำเร็จ | 1,418 |
| กรอกที่อยู่ | ชำระไม่สำเร็จ | 457 |
ลองแล้วจะเห็นอะไร
- สังเกตอะไร: เทียบกับหน้า force-directed-graph ที่ใช้ข้อมูลชุดเดียวกัน จะเห็นว่าเมทริกซ์อ่านคู่ใดคู่หนึ่งได้แม่นกว่า แต่บอกเส้นทางหลายขั้นไม่ได้
ข้อควรระวัง
- ★ เรียงตามตัวอักษรแทนการจัดกลุ่ม ซึ่งทำให้บล็อกที่เป็นกลุ่มย่อยกระจายจนมองไม่เห็น
- ใช้ลำดับแกนแถวกับแกนคอลัมน์ต่างกัน ทำให้เส้นทแยงมุมไม่มีความหมาย
- ไม่แยกช่องว่างจากค่าศูนย์ ทำให้ "ไม่มีข้อมูล" ปนกับ "ไม่มีการเชื่อมต่อ"
- ใช้กับเครือข่ายเบาบางที่กราฟแบบเส้นอ่านง่ายกว่ามาก
เมื่อไหร่ไม่ควรใช้กราฟนี้
- เครือข่ายเบาบางมีไม่ถึง 50 เส้นเชื่อม→ใช้แทน: force-directed-graph
- ต้องตามเส้นทางหลายขั้น→ใช้แทน: force-directed-graph หรือ flow-diagram
- โครงสร้างเป็นต้นไม้→ใช้แทน: node-link-tree