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

แผนภาพส่วนโค้งArc Diagram

ใช้เมื่อโหนดมีลำดับที่มีความหมายอยู่แล้ว

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

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

Arc diagram วางโหนดเรียงกันบนเส้นตรงแล้วลากส่วนโค้งเชื่อมคู่ที่เกี่ยวข้อง จุดแข็งคือรักษาลำดับของโหนดไว้ ซึ่งเป็นสิ่งที่กราฟเครือข่ายแบบจัดวางอิสระทำลายทิ้ง จึงเหมาะเมื่อลำดับมีความหมาย เช่น เวลา ตำแหน่งในข้อความ หรือขั้นตอน

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

เหมือนแผนที่รถไฟฟ้าที่สถานีเรียงตามเส้นทางจริง แล้วมีเส้นโค้งบอกว่าสถานีไหนเชื่อมถึงกันโดยตรง

ใช้ที่ไหนบ้าง — การอ้างอิงระหว่างบทในหนังสือ การเชื่อมโยงระหว่างเหตุการณ์ตามเวลา หรือความสัมพันธ์ระหว่างตัวละครตามลำดับการปรากฏ

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

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

ตัวอย่างคลาสสิก · Arc diagram ของโครงสร้างซ้ำในบทเพลง

Martin Wattenberg สร้าง The Shape of Song ที่แสดงท่อนที่ซ้ำกันในบทเพลงเป็นส่วนโค้งเชื่อมระหว่างตำแหน่งบนแกนเวลาของเพลง รูปแบบนี้ตรงกับข้อมูลพอดีเพราะเวลาในเพลงมีลำดับที่ชัดเจน และทำให้เห็นโครงสร้างของบทเพลงที่การฟังอย่างเดียวจับไม่ได้

Wikipedia · Arc diagram

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

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

Arc diagram เลือกทางตรงข้าม คือตรึงโหนดไว้บนเส้นตรงตามลำดับที่มีความหมาย แล้วยอมให้เส้นเชื่อมโค้งข้ามกันแทน

ผลคือผู้อ่านได้ข้อมูลสองชั้น ชั้นแรกคือลำดับของโหนดซึ่งอ่านจากแกนนอน ชั้นที่สองคือการเชื่อมโยงซึ่งอ่านจากส่วนโค้ง

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

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

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

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

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

คอลัมน์ทำหน้าที่ชนิดเข้ารหัสด้วยจำนวนค่าที่เหมาะหมายเหตุ
sourceโหนดต้นทางโหนดx5–40 โหนด★ ลำดับของโหนดบนแกนต้องมีความหมาย
targetโหนดปลายทางโหนดxชุดเดียวกับต้นทางระยะบนแกนคือระยะของการเชื่อม
value
ไม่บังคับ
น้ำหนักของการเชื่อมตัวเลขต่อเนื่องsizeบวกเท่านั้นใช้กำหนดความหนาของโค้ง

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

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

ค่าที่หายไป — โหนดที่ไม่มีการเชื่อมเลยต้องแสดงไว้บนแกนด้วย เพื่อให้เห็นว่ามีอยู่แต่โดดเดี่ยว

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

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

เกิน 60 เส้น ส่วนโค้งจะทับกันจนอ่านไม่ได้ — ใช้ adjacency-matrix

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

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

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

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

  • โหนดที่มีการเชื่อมมากที่สุด
  • การเชื่อมระยะไกลซึ่งมักน่าสนใจที่สุด
  • กลุ่มโหนดที่เชื่อมกันเองหนาแน่น
  • โหนดที่ไม่เชื่อมกับใครเลย

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

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

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

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

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

  • โหนดไหนเป็นศูนย์กลาง
  • มีการเชื่อมข้ามไปไกลไหม
  • โหนดที่อยู่ติดกันเชื่อมกันมากกว่าโหนดที่อยู่ไกลไหม

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

  • ลำดับของโหนดเรียงตามตัวอักษรโดยไม่มีเหตุผล ซึ่งทำลายจุดแข็งของกราฟนี้
  • เส้นเกิน 60 เส้นจนทับกัน

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

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

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

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

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

<โหนด> เชื่อมกับ <จำนวน> โหนด รวมถึงการเชื่อมข้ามไปยัง <โหนด> ที่อยู่ไกลออกไป

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

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

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

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

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

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

nodes = list(dict.fromkeys(list(df["source"]) + list(df["target"])))
pos = {n: i for i, n in enumerate(nodes)}          # ลำดับต้องมีความหมาย ไม่ใช่เรียงตามตัวอักษร
maxv = df["value"].max()
for _, r in df.iterrows():
    x0, x1 = pos[r["source"]], pos[r["target"]]
    ax.add_patch(Arc(((x0 + x1) / 2, 0), abs(x1 - x0), abs(x1 - x0) * 0.8,
                     theta1=0, theta2=180, lw=1.5 + r["value"] / maxv * 5,
                     color=plt.cm.Blues(0.35 + r["value"] / maxv * 0.55)))
ax.scatter(range(len(nodes)), [0] * len(nodes), s=80, color=C1, zorder=3)
ax.set_xticks(range(len(nodes))); ax.set_xticklabels(nodes, rotation=40, ha="right", fontsize=8)
ax.set_ylim(-0.3, len(nodes) * 0.45); ax.set_yticks([])
ax.spines[["left", "right", "top"]].set_visible(False)

ax.spines[["top", "right"]].set_visible(False)   # ลดเส้นที่ไม่ได้ให้ข้อมูล
fig.tight_layout()
fig.savefig("arc-diagram.png", dpi=160)
print("เขียน arc-diagram.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
จำนวนเส้นเชื่อม8
เส้นที่ยาวที่สุดดูสินค้า →
ดูข้อมูลเป็นตาราง (8 แถว)
arc diagram 9 โหนด 8 เส้น
จากไปน้ำหนัก
เข้าชมเว็บดูสินค้า7,975
เข้าชมเว็บออกทันที4,078
ดูสินค้าใส่ตะกร้า3,083
ดูสินค้าออกกลางทาง5,112
ใส่ตะกร้ากรอกที่อยู่1,952
ใส่ตะกร้าทิ้งตะกร้า1,166
กรอกที่อยู่ชำระเงินสำเร็จ1,418
กรอกที่อยู่ชำระไม่สำเร็จ457

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

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

ข้อควรระวัง

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

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

  • โหนดไม่มีลำดับที่มีความหมายใช้แทน: force-directed-graph
  • มีเส้นเชื่อมเกิน 60 เส้นใช้แทน: adjacency-matrix
  • สนใจปริมาณที่ไหลมากกว่าการเชื่อมใช้แทน: sankey-diagram

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

เทคนิคถัดไป · กราฟกรวย