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

กราฟสันเขาRidgeline Plot

เห็นการกระจายเลื่อนไปทีละกลุ่มเหมือนสันเขา

4
ขั้นสูงควรรู้ก่อน · อ่าน density plot เป็น
ลองเล่น

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

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

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

เหมือนมองแนวเทือกเขาจากด้านข้าง ยอดเขาที่ค่อย ๆ เลื่อนไปทางขวาบอกว่าอะไรบางอย่างกำลังเปลี่ยนไปอย่างเป็นระบบ

ใช้ที่ไหนบ้าง — การกระจายของอุณหภูมิรายเดือน คะแนนของแต่ละรุ่นการศึกษา หรือการกระจายของรายได้ตามช่วงอายุ

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

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

ตัวอย่างคลาสสิก · Joy Division กับปกอัลบั้ม Unknown Pleasures ปี 1979

ปกอัลบั้มที่เป็นเส้นสัญญาณจากพัลซาร์ซ้อนกันเป็นแนวสันเขา กลายเป็นที่มาของชื่อเล่น joyplot รูปแบบนี้ถูกนำกลับมาใช้จริงในงานข้อมูลเพราะมันเผยการเลื่อนของการกระจายได้ดีกว่าการวางกราฟแยกกัน

Wikipedia · Unknown Pleasures

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

เมื่อต้องเทียบการกระจายของ 12 เดือน การวาง violin plot 12 อันเรียงกันจะแคบจนอ่านรูปร่างไม่ได้ และการวาง density plot ซ้อนทับกันก็จะกลายเป็นเส้นพันกัน

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

สิ่งที่กราฟนี้ทำได้ดีเป็นพิเศษคือเผย "การเลื่อน" ถ้ายอดของแต่ละแถวค่อย ๆ ขยับไปทางขวา สายตาจะจับรูปแบบนั้นได้ทันทีในฐานะแนวสันเขาที่เอียง

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

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

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

รูปทรงของข้อมูลข้อมูลดิบรายแถว (ยังไม่สรุป)
จำนวนมิติที่เข้ารหัสได้3 มิติ
จำนวนแถวที่เหมาะ6–15 กลุ่ม × 50–500 จุดขั้นต่ำ 120 แถว
เส้นฐานศูนย์ต้องเริ่มที่ศูนย์ความหนาแน่นวัดจากศูนย์ และฐานของทุกเส้นต้องอยู่ที่ระดับเดียวกันในแถวของมัน

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

คอลัมน์ทำหน้าที่ชนิดเข้ารหัสด้วยจำนวนค่าที่เหมาะหมายเหตุ
groupกลุ่มที่มีลำดับมีลำดับrow4–20 กลุ่ม★ ต้องมีลำดับที่มีความหมาย เช่น เดือนหรือช่วงอายุ
valueค่าที่วัดได้ตัวเลขต่อเนื่องxต่อเนื่องข้อมูลดิบ อย่างน้อย 30 จุดต่อกลุ่ม

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

  1. ตรวจว่ากลุ่มมีลำดับ
  2. คำนวณความหนาแน่นด้วย bandwidth เดียวกันทุกกลุ่ม
  3. ปรับระดับการซ้อนให้เห็นฐานของเส้น

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

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

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

เกิน 25 กลุ่มจะสูงเกินหน้าจอ และต่ำกว่า 4 กลุ่มไม่คุ้มกับความซับซ้อน

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

group,value

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

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

  • การเลื่อนของยอดจากกลุ่มหนึ่งไปอีกกลุ่ม
  • กลุ่มที่รูปร่างต่างจากกลุ่มข้างเคียง
  • กลุ่มที่มีสองยอด

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

  • ไม่บอกจำนวนข้อมูลของแต่ละกลุ่ม
  • ส่วนล่างของเส้นถูกบังโดยเส้นถัดไป จึงอ่านหางล่างไม่ครบ

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

  1. มองแนวสันเขารวมว่าเอียงไปทางไหน
  2. ดูรูปร่างของแต่ละแถวว่ามีกี่ยอด
  3. หาแถวที่ผิดจากแนวโน้ม

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

  • การกระจายเปลี่ยนไปอย่างไรตามลำดับของกลุ่ม
  • มีกลุ่มไหนที่ผิดจากแนวโน้มรวม

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

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

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

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

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

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

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

การกระจายของ <ตัวแปร> เลื่อนไปทาง <ทิศทาง> อย่างต่อเนื่องตั้งแต่ <กลุ่มแรก> ถึง <กลุ่มสุดท้าย>

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

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

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

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

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

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

groups = list(df["group"].unique())
grid = np.linspace(df["value"].min(), df["value"].max(), 200)
for i, g in enumerate(reversed(groups)):
    v = df[df["group"] == g]["value"]
    dens = gaussian_kde(v)(grid); dens = dens / dens.max() * 1.6   # ปรับให้ซ้อนเหลื่อมกันได้
    ax.fill_between(grid, i, i + dens, color=plt.cm.Blues(0.3 + i / len(groups) * 0.5), lw=1.2, ec=SURFACE)
    ax.text(grid[0], i + 0.1, g, ha="right", fontsize=9)
ax.set_yticks([]); ax.set_xlabel("ค่าที่วัดได้")

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

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

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

ข้อมูลตัวอย่าง · 320 แถว · seed 101● คำนวณใหม่ในเบราว์เซอร์ทันทีที่ปรับค่า
มองแนวสันเขารวม
50.060.070.080.090.0สาขา Aสาขา A · มัธยฐาน 57.6สาขา Bสาขา B · มัธยฐาน 66.3สาขา Cสาขา C · มัธยฐาน 61.7สาขา Dสาขา D · มัธยฐาน 73.7

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

จำนวนกลุ่ม4
การเลื่อนของมัธยฐาน16.1
ข้อมูลต่อกลุ่ม80
ดูข้อมูลเป็นตาราง (4 แถว)
ridgeline plot 4 กลุ่ม
กลุ่มมัธยฐานต่ำสุดสูงสุด
สาขา A57.650.067.1
สาขา B66.355.976.6
สาขา C61.755.668.1
สาขา D73.762.684.9

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

  • สังเกตอะไร: มองภาพรวมโดยไม่อ่านตัวเลข จะเห็นว่ายอดของแต่ละแถวขยับไปทางไหน ซึ่งเป็นรูปแบบที่การดูทีละกลุ่มมองไม่เห็น

ข้อควรระวัง

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

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

  • กลุ่มไม่มีลำดับที่มีความหมายใช้แทน: violin-plot หรือ box-plot
  • มีน้อยกว่า 4 กลุ่มใช้แทน: density-plot ซ้อนกัน
  • ต้องอ่านค่าสรุปให้แม่นใช้แทน: box-plot

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

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