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

เมทริกซ์ความเชื่อมโยงAdjacency Matrix

อ่านเครือข่ายหนาแน่นได้โดยไม่มีก้อนขนแมว

4
ขั้นสูงควรรู้ก่อน · อ่าน heatmap เป็นและเข้าใจข้อมูลเครือข่าย
ลองเล่น

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

Adjacency matrix วางโหนดทั้งแถวและคอลัมน์แล้วระบายช่องที่มีการเชื่อมต่อ ข้อดีที่ชัดเจนคือไม่มีเส้นทับกันเลยไม่ว่าเครือข่ายจะหนาแน่นแค่ไหน แลกกับการที่เส้นทางหลายขั้นซึ่งเป็นจุดแข็งของกราฟแบบเส้นกลับอ่านแทบไม่ได้

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

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

ใช้ที่ไหนบ้าง — เครือข่ายหนาแน่นที่กราฟแบบเส้นอ่านไม่ได้ เมทริกซ์การค้าระหว่างประเทศ หรือการเรียกใช้ระหว่างบริการในระบบ

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

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

ตัวอย่างคลาสสิก · เมทริกซ์การเรียกใช้ระหว่างบริการในระบบไมโครเซอร์วิส

ระบบที่มีบริการหลายสิบตัววาดเป็นกราฟแบบเส้นแล้วกลายเป็นก้อนขนแมวทันที เมื่อเปลี่ยนเป็นเมทริกซ์และเรียงด้วยอัลกอริทึมจัดกลุ่ม บล็อกสี่เหลี่ยมที่ปรากฏขึ้นก็เผยขอบเขตของระบบย่อยที่แท้จริง ซึ่งมักไม่ตรงกับผังที่ทีมเขียนไว้

Wikipedia · Adjacency matrix

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

ปัญหาใหญ่ที่สุดของกราฟแบบเส้นคือเมื่อเส้นเชื่อมเยอะ เส้นจะทับกันจนกลายเป็นก้อนขนแมวที่ไม่บอกอะไรเลย

Adjacency matrix แก้ที่รากของปัญหา ด้วยการเลิกใช้เส้นทั้งหมด แล้วเปลี่ยนแต่ละความสัมพันธ์เป็นช่องหนึ่งช่องในตาราง

ผลคือไม่ว่าเครือข่ายจะหนาแน่นแค่ไหน ภาพก็ยังอ่านได้เท่าเดิม เพราะช่องไม่มีทางทับกัน ซึ่งเป็นข้อได้เปรียบที่เด็ดขาดกับเครือข่ายใหญ่

ราคาที่จ่ายอย่างแรกคือเส้นทางหลายขั้นหายไป การถามว่า A ไป C ผ่าน B ได้ไหมนั้นดูจากกราฟแบบเส้นใช้เวลาวินาทีเดียว แต่ในเมทริกซ์ต้องไล่สองช่องแยกกัน

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

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

รูปทรงของข้อมูลรายการเส้นเชื่อม source–target–value
จำนวนมิติที่เข้ารหัสได้3 มิติ
จำนวนแถวที่เหมาะ15–80 โหนดขั้นต่ำ 6 แถว
เส้นฐานศูนย์ไม่เกี่ยวข้องค่าเข้ารหัสด้วยสี ไม่มีแกนค่า

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

คอลัมน์ทำหน้าที่ชนิดเข้ารหัสด้วยจำนวนค่าที่เหมาะหมายเหตุ
sourceโหนดแถวโหนดrow10–200 โหนดรองรับโหนดได้มากกว่ากราฟแบบเส้นมาก
targetโหนดคอลัมน์โหนดcolumnชุดเดียวกับ sourceต้องใช้ชุดและลำดับเดียวกันทั้งสองแกน
valueน้ำหนักการเชื่อมต่อตัวเลขต่อเนื่องcolorศูนย์ถึงสูงสุดช่องว่างแปลว่าไม่มีการเชื่อมต่อ

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

  1. ★ เรียงโหนดด้วยอัลกอริทึมจัดกลุ่ม ไม่ใช่ตามตัวอักษร
  2. ใช้ลำดับเดียวกันทั้งสองแกน
  3. ตัดสินใจว่าเมทริกซ์สมมาตรหรือมีทิศทาง

ค่าที่หายไป — ช่องที่ไม่มีข้อมูลต้องแยกจากช่องที่มีค่าศูนย์ด้วยพื้นหลังต่างกัน

สเกลของแกน — ใช้สเกลสีลำดับเดียวไล่อ่อนไปเข้ม และแสดงช่วงค่าในคำอธิบายสีเสมอ

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

เกิน 200 โหนด ช่องเล็กจนกดไม่ได้และชื่อแกนอ่านไม่ออก

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

source,target,value
เข้าชมเว็บ,ดูสินค้า,7975
เข้าชมเว็บ,ออกทันที,4078

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

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

  • บล็อกสี่เหลี่ยมทึบซึ่งคือกลุ่มที่เชื่อมกันครบทุกคู่
  • แถวหรือคอลัมน์ที่เข้มทั้งแนวซึ่งคือโหนดศูนย์กลาง
  • ความสมมาตรหรือไม่สมมาตรของความสัมพันธ์

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

  • ★ เส้นทางหลายขั้นอ่านแทบไม่ได้ ซึ่งเป็นสิ่งที่กราฟแบบเส้นทำได้ทันที
  • โครงสร้างภาพรวมของเครือข่ายเห็นยากกว่ากราฟแบบเส้น

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

  1. มองหาบล็อกทึบตามแนวเส้นทแยงมุมซึ่งคือกลุ่มย่อย
  2. ดูแถวที่เข้มทั้งแนวซึ่งคือโหนดที่เชื่อมกับทุกคน
  3. เทียบครึ่งบนกับครึ่งล่างเพื่อดูความสมมาตร

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

  • A กับ B เชื่อมกันไหมและแรงแค่ไหน
  • มีกลุ่มที่เชื่อมกันครบทุกคู่ไหม
  • โหนดไหนเชื่อมกับคนอื่นมากที่สุด

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

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

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

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

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

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

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

เครือข่าย <จำนวน> โหนด โดยเห็นกลุ่มที่เชื่อมกันแน่น <จำนวน> กลุ่ม

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

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

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

ข้อมูลตัวอย่าง · 8 แถว · seed 239● คำนวณใหม่ในเบราว์เซอร์ทันทีที่ปรับค่า
บล็อกคือกลุ่มที่เชื่อมกันครบ
เข้าชมเว็บดูสินค้าออกทันทีใส่ตะกร้าออกกลางทางกรอกที่อยู่ทิ้งตะกร้าชำระเงินสำเร็จชำระไม่สำเร็จเข้าชมเว็บดูสินค้าออกทันทีใส่ตะกร้าออกกลางทางกรอกที่อยู่ทิ้งตะกร้าชำระเงินสำเร็จชำระไม่สำเร็จเข้าชมเว็บ → เข้าชมเว็บ · ไม่มีการเชื่อมเข้าชมเว็บ → ดูสินค้า · 7,975เข้าชมเว็บ → ออกทันที · 4,078เข้าชมเว็บ → ใส่ตะกร้า · ไม่มีการเชื่อมเข้าชมเว็บ → ออกกลางทาง · ไม่มีการเชื่อมเข้าชมเว็บ → กรอกที่อยู่ · ไม่มีการเชื่อมเข้าชมเว็บ → ทิ้งตะกร้า · ไม่มีการเชื่อมเข้าชมเว็บ → ชำระเงินสำเร็จ · ไม่มีการเชื่อมเข้าชมเว็บ → ชำระไม่สำเร็จ · ไม่มีการเชื่อมดูสินค้า → เข้าชมเว็บ · ไม่มีการเชื่อมดูสินค้า → ดูสินค้า · ไม่มีการเชื่อมดูสินค้า → ออกทันที · ไม่มีการเชื่อมดูสินค้า → ใส่ตะกร้า · 3,083ดูสินค้า → ออกกลางทาง · 5,112ดูสินค้า → กรอกที่อยู่ · ไม่มีการเชื่อมดูสินค้า → ทิ้งตะกร้า · ไม่มีการเชื่อมดูสินค้า → ชำระเงินสำเร็จ · ไม่มีการเชื่อมดูสินค้า → ชำระไม่สำเร็จ · ไม่มีการเชื่อมออกทันที → เข้าชมเว็บ · ไม่มีการเชื่อมออกทันที → ดูสินค้า · ไม่มีการเชื่อมออกทันที → ออกทันที · ไม่มีการเชื่อมออกทันที → ใส่ตะกร้า · ไม่มีการเชื่อมออกทันที → ออกกลางทาง · ไม่มีการเชื่อมออกทันที → กรอกที่อยู่ · ไม่มีการเชื่อมออกทันที → ทิ้งตะกร้า · ไม่มีการเชื่อมออกทันที → ชำระเงินสำเร็จ · ไม่มีการเชื่อมออกทันที → ชำระไม่สำเร็จ · ไม่มีการเชื่อมใส่ตะกร้า → เข้าชมเว็บ · ไม่มีการเชื่อมใส่ตะกร้า → ดูสินค้า · ไม่มีการเชื่อมใส่ตะกร้า → ออกทันที · ไม่มีการเชื่อมใส่ตะกร้า → ใส่ตะกร้า · ไม่มีการเชื่อมใส่ตะกร้า → ออกกลางทาง · ไม่มีการเชื่อมใส่ตะกร้า → กรอกที่อยู่ · 1,952ใส่ตะกร้า → ทิ้งตะกร้า · 1,166ใส่ตะกร้า → ชำระเงินสำเร็จ · ไม่มีการเชื่อมใส่ตะกร้า → ชำระไม่สำเร็จ · ไม่มีการเชื่อมออกกลางทาง → เข้าชมเว็บ · ไม่มีการเชื่อมออกกลางทาง → ดูสินค้า · ไม่มีการเชื่อมออกกลางทาง → ออกทันที · ไม่มีการเชื่อมออกกลางทาง → ใส่ตะกร้า · ไม่มีการเชื่อมออกกลางทาง → ออกกลางทาง · ไม่มีการเชื่อมออกกลางทาง → กรอกที่อยู่ · ไม่มีการเชื่อมออกกลางทาง → ทิ้งตะกร้า · ไม่มีการเชื่อมออกกลางทาง → ชำระเงินสำเร็จ · ไม่มีการเชื่อมออกกลางทาง → ชำระไม่สำเร็จ · ไม่มีการเชื่อมกรอกที่อยู่ → เข้าชมเว็บ · ไม่มีการเชื่อมกรอกที่อยู่ → ดูสินค้า · ไม่มีการเชื่อมกรอกที่อยู่ → ออกทันที · ไม่มีการเชื่อมกรอกที่อยู่ → ใส่ตะกร้า · ไม่มีการเชื่อมกรอกที่อยู่ → ออกกลางทาง · ไม่มีการเชื่อมกรอกที่อยู่ → กรอกที่อยู่ · ไม่มีการเชื่อมกรอกที่อยู่ → ทิ้งตะกร้า · ไม่มีการเชื่อมกรอกที่อยู่ → ชำระเงินสำเร็จ · 1,418กรอกที่อยู่ → ชำระไม่สำเร็จ · 457ทิ้งตะกร้า → เข้าชมเว็บ · ไม่มีการเชื่อมทิ้งตะกร้า → ดูสินค้า · ไม่มีการเชื่อมทิ้งตะกร้า → ออกทันที · ไม่มีการเชื่อมทิ้งตะกร้า → ใส่ตะกร้า · ไม่มีการเชื่อมทิ้งตะกร้า → ออกกลางทาง · ไม่มีการเชื่อมทิ้งตะกร้า → กรอกที่อยู่ · ไม่มีการเชื่อมทิ้งตะกร้า → ทิ้งตะกร้า · ไม่มีการเชื่อมทิ้งตะกร้า → ชำระเงินสำเร็จ · ไม่มีการเชื่อมทิ้งตะกร้า → ชำระไม่สำเร็จ · ไม่มีการเชื่อมชำระเงินสำเร็จ → เข้าชมเว็บ · ไม่มีการเชื่อมชำระเงินสำเร็จ → ดูสินค้า · ไม่มีการเชื่อมชำระเงินสำเร็จ → ออกทันที · ไม่มีการเชื่อมชำระเงินสำเร็จ → ใส่ตะกร้า · ไม่มีการเชื่อมชำระเงินสำเร็จ → ออกกลางทาง · ไม่มีการเชื่อมชำระเงินสำเร็จ → กรอกที่อยู่ · ไม่มีการเชื่อมชำระเงินสำเร็จ → ทิ้งตะกร้า · ไม่มีการเชื่อมชำระเงินสำเร็จ → ชำระเงินสำเร็จ · ไม่มีการเชื่อมชำระเงินสำเร็จ → ชำระไม่สำเร็จ · ไม่มีการเชื่อมชำระไม่สำเร็จ → เข้าชมเว็บ · ไม่มีการเชื่อมชำระไม่สำเร็จ → ดูสินค้า · ไม่มีการเชื่อมชำระไม่สำเร็จ → ออกทันที · ไม่มีการเชื่อมชำระไม่สำเร็จ → ใส่ตะกร้า · ไม่มีการเชื่อมชำระไม่สำเร็จ → ออกกลางทาง · ไม่มีการเชื่อมชำระไม่สำเร็จ → กรอกที่อยู่ · ไม่มีการเชื่อมชำระไม่สำเร็จ → ทิ้งตะกร้า · ไม่มีการเชื่อมชำระไม่สำเร็จ → ชำระเงินสำเร็จ · ไม่มีการเชื่อมชำระไม่สำเร็จ → ชำระไม่สำเร็จ · ไม่มีการเชื่อม

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

ขนาดเมทริกซ์9 × 9
ช่องที่มีค่า8 จาก 81
ความหนาแน่น9.9%
ดูข้อมูลเป็นตาราง (8 แถว)
adjacency matrix 9 × 9
จากไปน้ำหนัก
เข้าชมเว็บดูสินค้า7,975
เข้าชมเว็บออกทันที4,078
ดูสินค้าใส่ตะกร้า3,083
ดูสินค้าออกกลางทาง5,112
ใส่ตะกร้ากรอกที่อยู่1,952
ใส่ตะกร้าทิ้งตะกร้า1,166
กรอกที่อยู่ชำระเงินสำเร็จ1,418
กรอกที่อยู่ชำระไม่สำเร็จ457

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

  • สังเกตอะไร: เทียบกับหน้า force-directed-graph ที่ใช้ข้อมูลชุดเดียวกัน จะเห็นว่าเมทริกซ์อ่านคู่ใดคู่หนึ่งได้แม่นกว่า แต่บอกเส้นทางหลายขั้นไม่ได้

ข้อควรระวัง

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

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

  • เครือข่ายเบาบางมีไม่ถึง 50 เส้นเชื่อมใช้แทน: force-directed-graph
  • ต้องตามเส้นทางหลายขั้นใช้แทน: force-directed-graph หรือ flow-diagram
  • โครงสร้างเป็นต้นไม้ใช้แทน: node-link-tree

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

เทคนิคถัดไป · ไฮฟ์พล็อต