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

ไฮฟ์พล็อตHive Plot

แก้ปัญหาตำแหน่งไม่มีความหมายของกราฟเครือข่าย

5
เฉพาะทางควรรู้ก่อน · เข้าใจข้อจำกัดของ force-directed graph
ลองเล่น

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

Hive plot จัดโหนดเข้าแกนตรงสองถึงสามแกนตามบทบาท แล้ววางตำแหน่งบนแกนตามค่าที่เลือก จุดแข็งคือตำแหน่งทุกจุดมีความหมายและภาพเดิมซ้ำได้เสมอ ต่างจาก force-directed ที่ตำแหน่งไม่มีความหมาย แลกกับการที่ต้องมีเกณฑ์จัดบทบาทที่ดีมาก่อน

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

เหมือนแผนผังที่นั่งในงานแต่งที่จัดคนตามฝ่ายเจ้าบ่าว ฝ่ายเจ้าสาว และเพื่อนร่วมงาน ซึ่งตำแหน่งบอกความสัมพันธ์จริง ๆ

ใช้ที่ไหนบ้าง — เครือข่ายที่โหนดมีบทบาทชัดเจนอยู่แล้ว เช่น เครือข่ายยีนที่แบ่งตามหน้าที่ หรือเครือข่ายองค์กรที่แบ่งตามแผนก

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

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

ตัวอย่างคลาสสิก · Hive plot ในงานวิเคราะห์เครือข่ายจีโนม

Martin Krzywinski เสนอ hive plot เพื่อแก้ปัญหาที่เครือข่ายชีววิทยาวาดด้วย force-directed แล้วได้ภาพต่างกันทุกครั้ง เมื่อจัดยีนเข้าแกนตามหน้าที่ที่รู้อยู่แล้ว ภาพก็กลายเป็นสิ่งที่เทียบข้ามการทดลองได้จริง

Wikipedia · Hive plot

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

ปัญหาที่ค้างอยู่ของ force-directed graph คือตำแหน่งไม่มีความหมาย ซึ่งทำให้ภาพเดิมซ้ำไม่ได้และผู้อ่านตีความผิดเสมอ

Hive plot แก้ด้วยการเลิกให้คอมพิวเตอร์หาตำแหน่งเอง แล้วให้คนกำหนดกติกาแทน โดยแบ่งโหนดเข้าแกนตามบทบาท และวางบนแกนตามค่าที่เลือก

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

ราคาที่จ่ายอย่างแรกคือคุณภาพของภาพขึ้นกับเกณฑ์จัดบทบาททั้งหมด ถ้าเกณฑ์ไม่มีความหมาย ภาพจะดูเป็นระเบียบสวยงามแต่ไม่บอกอะไรเลย ซึ่งอันตรายกว่าภาพที่ดูรก

อย่างที่สองคือมันใช้ได้กับเครือข่ายที่มีบทบาทชัดเจนอยู่แล้วเท่านั้น ซึ่งเป็นกรณีที่ไม่ได้พบบ่อย จึงเป็นกราฟเฉพาะทางมากกว่าจะเป็นตัวเลือกทั่วไป

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

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

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

คอลัมน์ทำหน้าที่ชนิดเข้ารหัสด้วยจำนวนค่าที่เหมาะหมายเหตุ
sourceโหนดต้นทางโหนดangle10–120 โหนดต้องมีเกณฑ์จัดเข้าแกนได้
targetโหนดปลายทางโหนดangleชุดเดียวกับ sourceเส้นเชื่อมข้ามแกนเป็นเส้นโค้ง
value
ไม่บังคับ
น้ำหนักความสัมพันธ์ตัวเลขต่อเนื่องsizeบวกเท่านั้นควบคุมความหนาของเส้น

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

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

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

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

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

เกิน 4 แกน ผู้อ่านตามไม่ทันว่าเส้นไหนไปแกนไหน

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

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

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

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

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

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

  • ★ ถ้าเกณฑ์จัดบทบาทไม่มีความหมาย ภาพจะดูเป็นระเบียบแต่ไม่บอกอะไร
  • ตามเส้นทีละเส้นได้ยากเมื่อเส้นโค้งซ้อนกันใกล้ศูนย์กลาง

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

  1. อ่านชื่อแกนก่อนว่าแต่ละแกนคือบทบาทอะไร
  2. ดูว่าเส้นส่วนใหญ่พาดระหว่างแกนคู่ไหน
  3. ดูโหนดที่มีเส้นออกไปทุกแกน

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

  • บทบาทไหนเชื่อมกับบทบาทไหนมากที่สุด
  • มีโหนดที่เชื่อมข้ามทุกบทบาทไหม
  • โครงสร้างการเชื่อมต่อเปลี่ยนไปไหมเมื่อเทียบสองช่วงเวลา

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

  • ไม่ระบุว่าจัดบทบาทด้วยเกณฑ์อะไร
  • ใช้เกินสามแกนจนตามไม่ทัน
  • ไม่ระบุว่าตำแหน่งบนแกนมาจากค่าอะไร

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

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

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

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

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

เครือข่าย <จำนวน> โหนด จัดตาม <เกณฑ์บทบาท>

06เอาไปใช้ต่อ

โค้ดทุกชิ้นอ่านไฟล์ hive-plot-sample.csv ชุดเดียวกับที่ Playground ใช้ และตัวเลขในโค้ดเปลี่ยนตามค่าที่คุณปรับด้านล่าง

# ติดตั้ง: pip install "matplotlib==3.10.*" "pandas==2.*"
# ดาวน์โหลด hive-plot-sample.csv จากหน้านี้ แล้ววางไว้ข้างสคริปต์
import matplotlib
matplotlib.use("Agg")   # รันแบบไม่มีหน้าจอ ถ้ารันในเครื่องตัวเองลบบรรทัดนี้ได้
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import networkx as nx

C1, C2, C3 = "#2a78d6", "#eb6834", "#1baf7a"   # palette ของคลัง เปลี่ยนเป็นสีองค์กรได้
INK, SURFACE = "#0b0b0b", "#fcfcfb"

df = pd.read_csv("hive-plot-sample.csv")
df["value"] = pd.to_numeric(df["value"], errors="coerce")
NOTE = "axes"   # ← ค่าจาก Playground

fig, ax = plt.subplots(figsize=(7.6, 4.2), facecolor=SURFACE)
ax.set_facecolor(SURFACE)

G = nx.from_pandas_edgelist(df, "source", "target", edge_attr="value")
nodes = list(G)
role = {n: G.degree(n) % 3 for n in nodes}              # แทนที่ด้วยเกณฑ์จริงของคุณ
pos = {}
for ax_i in range(3):
    members = sorted([n for n in nodes if role[n] == ax_i], key=lambda n: G.degree(n))
    a = ax_i / 3 * 2 * np.pi - np.pi / 2
    for i, n in enumerate(members):
        r = 0.3 + 0.7 * (i / max(1, len(members) - 1))
        pos[n] = (np.cos(a) * r, np.sin(a) * r)
for ax_i in range(3):
    a = ax_i / 3 * 2 * np.pi - np.pi / 2
    ax.plot([np.cos(a) * 0.25, np.cos(a) * 1.05], [np.sin(a) * 0.25, np.sin(a) * 1.05],
            color=PALETTE[ax_i], linewidth=2.5)
for a_, b_ in G.edges():
    ax.plot(*zip(pos[a_], (0, 0), pos[b_]), color="#c9c6bd", linewidth=1.2, alpha=0.7)
for n in nodes:
    ax.plot(*pos[n], "o", markersize=6, color=PALETTE[role[n]])
ax.set_aspect("equal"); ax.axis("off")

ax.spines[["top", "right"]].set_visible(False)   # ลดเส้นที่ไม่ได้ให้ข้อมูล
fig.tight_layout()
fig.savefig("hive-plot.png", dpi=160)
print("เขียน hive-plot.png แล้ว ·", len(df), "แถว")

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

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

ข้อมูลตัวอย่าง · 8 แถว · seed 239● คำนวณใหม่ในเบราว์เซอร์ทันทีที่ปรับค่า
ทุกตำแหน่งมีที่มา
บทบาทที่ 1บทบาทที่ 2บทบาทที่ 3เข้าชมเว็บดูสินค้าออกทันทีใส่ตะกร้าออกกลางทางกรอกที่อยู่ทิ้งตะกร้าชำระเงินสำเร็จชำระไม่สำเร็จ

ต้องมีเกณฑ์จัดโหนดเข้าแกนที่มีความหมายก่อน ไม่อย่างนั้นภาพจะดูเป็นระเบียบทั้งที่ไม่ได้บอกอะไร

จำนวนแกน3
จำนวนโหนด9
เส้นเชื่อม8
ดูข้อมูลเป็นตาราง (9 แถว)
hive plot 3 แกน 9 โหนด
โหนดบทบาท
เข้าชมเว็บบทบาทที่ 2
ดูสินค้าบทบาทที่ 3
ออกทันทีบทบาทที่ 3
ใส่ตะกร้าบทบาทที่ 1
ออกกลางทางบทบาทที่ 2
กรอกที่อยู่บทบาทที่ 3
ทิ้งตะกร้าบทบาทที่ 2
ชำระเงินสำเร็จบทบาทที่ 3
ชำระไม่สำเร็จบทบาทที่ 2

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

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

ข้อควรระวัง

  1. ★ ใช้เกณฑ์จัดบทบาทที่ไม่มีความหมาย ทำให้ภาพดูเป็นระเบียบแต่ไม่บอกอะไร
  2. ไม่บอกผู้อ่านว่าแกนแบ่งตามอะไรและตำแหน่งบนแกนมาจากค่าอะไร
  3. ใช้เกินสามแกนจนผู้อ่านตามเส้นไม่ทัน
  4. เลือกกราฟนี้ทั้งที่เครือข่ายไม่มีบทบาทชัดเจนอยู่แล้ว

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

  • โหนดไม่มีบทบาทที่แบ่งได้ชัดเจนใช้แทน: force-directed-graph
  • เครือข่ายหนาแน่นมากใช้แทน: adjacency-matrix
  • ผู้อ่านไม่คุ้นกับกราฟเฉพาะทางใช้แทน: chord-diagram ที่อ่านง่ายกว่า

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

เทคนิคถัดไป · การมัดเส้นเชื่อม