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

กราฟการแจกแจงสะสมECDF Plot

อ่านได้ตรงว่ากี่เปอร์เซ็นต์ต่ำกว่าค่านี้

4
ขั้นสูงควรรู้ก่อน · เข้าใจแนวคิดเปอร์เซ็นไทล์
ลองเล่น

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

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

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

เหมือนยืนที่เส้นชัยแล้วนับว่ามีคนเข้าเส้นไปแล้วกี่เปอร์เซ็นต์ ณ เวลาหนึ่ง ๆ ไม่ต้องแบ่งช่วงเวลาเป็นถัง

ใช้ที่ไหนบ้าง — ตอบคำถามเชิงข้อตกลงบริการ เช่น 95% ของคำขอเสร็จภายในกี่วินาที เทียบการกระจายของสองกลุ่มอย่างแม่นยำ หรือใช้แทนฮิสโทแกรมเมื่อไม่อยากเลือก bin

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

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

ตัวอย่างคลาสสิก · กราฟเปอร์เซ็นไทล์ของเวลาตอบสนองในงานวิศวกรรมระบบ

ทีมที่ดูแลระบบออนไลน์ใช้ ECDF เป็นมาตรฐาน เพราะคำถามที่ต้องตอบคือ "99% ของคำขอเสร็จภายในกี่มิลลิวินาที" ซึ่งอ่านจาก ECDF ได้ตรง ๆ ขณะที่ค่าเฉลี่ยกลบปัญหาที่หางขวาไว้มิด

Google SRE Book · Monitoring distributed systems

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

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

ECDF ไม่มีปัญหานี้เลย มันแค่เรียงข้อมูลแล้วถามว่า ณ ค่าใดค่าหนึ่ง มีข้อมูลกี่เปอร์เซ็นต์ที่ต่ำกว่าหรือเท่ากับค่านั้น คำตอบมีแค่แบบเดียว ไม่มีอะไรให้เลือก

ผลพลอยได้ที่มีค่ามากคือการอ่านเปอร์เซ็นไทล์ ถ้าอยากรู้ว่า 90% ของคำขอเสร็จภายในกี่วินาที ก็ลากเส้นแนวนอนที่ 0.9 แล้วอ่านค่าบนแกนนอน ซึ่งเป็นสิ่งที่ฮิสโทแกรมทำไม่ได้

การเทียบสองกลุ่มก็ทำได้ดี เพราะเส้น ECDF สองเส้นซ้อนกันได้โดยไม่บังกันเหมือนฮิสโทแกรม และระยะห่างในแนวตั้งระหว่างสองเส้นก็มีความหมายทางสถิติจริง

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

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

รูปทรงของข้อมูลข้อมูลดิบรายแถว (ยังไม่สรุป)
จำนวนมิติที่เข้ารหัสได้2 มิติ
จำนวนแถวที่เหมาะ50–100,000 แถวขั้นต่ำ 20 แถว
เส้นฐานศูนย์ต้องเริ่มที่ศูนย์แกนตั้งคือสัดส่วนสะสมซึ่งต้องเริ่มที่ศูนย์และจบที่หนึ่ง

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

คอลัมน์ทำหน้าที่ชนิดเข้ารหัสด้วยจำนวนค่าที่เหมาะหมายเหตุ
valueค่าที่วัดได้ตัวเลขต่อเนื่องxต่อเนื่องข้อมูลดิบ ไม่ต้องสรุปมาก่อน และไม่ต้องเลือกพารามิเตอร์ใด ๆ

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

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

ค่าที่หายไป — ตัดค่าว่างและรายงานจำนวน เพราะสัดส่วนสะสมคำนวณจากจำนวนที่เหลือ

สเกลของแกน — แกนนอนตามค่าจริง ใช้ log ได้ถ้าข้อมูลเบ้ แกนตั้งเป็น 0 ถึง 1 เสมอ

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

ต่ำกว่า 20 แถว ขั้นบันไดจะหยาบจนอ่านเปอร์เซ็นไทล์ได้ไม่ละเอียด

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

value

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

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

  • เปอร์เซ็นไทล์ใด ๆ อ่านได้ตรงจากกราฟ
  • ช่วงที่เส้นชันคือช่วงที่ข้อมูลหนาแน่น
  • ช่วงที่เส้นแบนคือช่วงที่แทบไม่มีข้อมูล

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

  • ไม่แสดงยอดของการกระจายอย่างตรงไปตรงมา ต้องอ่านจากความชัน
  • ผู้อ่านทั่วไปมักตีความรูปร่างผิดถ้าไม่เคยเห็นมาก่อน

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

  1. ลากเส้นแนวนอนที่สัดส่วนที่สนใจแล้วอ่านค่าบนแกนนอน
  2. ดูช่วงที่เส้นชันเพื่อหาช่วงที่ข้อมูลหนาแน่น
  3. ดูช่วงที่เส้นแบนเพื่อหาช่องว่างของข้อมูล

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

  • กี่เปอร์เซ็นต์ที่ต่ำกว่าค่านี้
  • ค่าที่เปอร์เซ็นไทล์ที่ 95 คือเท่าไร
  • สองกลุ่มนี้มีการกระจายต่างกันตรงไหน

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

  • เส้นไม่ได้เริ่มที่ 0 หรือจบที่ 1
  • ใช้กับข้อมูลน้อยจนขั้นบันไดหยาบมาก

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

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

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

  1. ลากเส้นประที่เปอร์เซ็นไทล์สำคัญ เช่น 50, 90, 95 พร้อมป้ายค่า
  2. เขียนจำนวนข้อมูลไว้
  3. ถ้าเทียบหลายกลุ่ม ให้ติดป้ายไว้ปลายเส้น

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

90% ของ <สิ่งที่วัด> อยู่ต่ำกว่า <ค่า> ขณะที่ค่ากลางอยู่ที่ <ค่า>

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

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

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

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

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

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

v = np.sort(df["value"].dropna().to_numpy())
p = np.arange(1, len(v) + 1) / len(v)           # สัดส่วนสะสม ไม่มีพารามิเตอร์ให้เลือก
ax.step(v, p, where="post", color=C1, linewidth=2)
for q in [0.25, 0.5, 0.9]:
    val = np.quantile(v, q)
    ax.plot([v.min(), val], [q, q], "--", color="#c9c6bd", linewidth=1)
    ax.plot([val, val], [0, q], "--", color="#c9c6bd", linewidth=1)
    ax.annotate(f"{int(q*100)}% ≤ {val:,.1f}", (val, q), xytext=(6, -12), textcoords="offset points", fontsize=9)
ax.set_ylim(0, 1); ax.set_xlabel("ค่าที่วัดได้"); ax.set_ylabel("สัดส่วนสะสม")

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

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

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

ข้อมูลตัวอย่าง · 400 แถว · seed 89● คำนวณใหม่ในเบราว์เซอร์ทันทีที่ปรับค่า
ลากเส้นแนวนอนแล้วอ่านค่าบนแกนนอน
0%20%40%60%80%100%สัดส่วนสะสม50.060.070.080.0ค่าที่วัดได้25% ≤ 58.350% ≤ 62.675% ≤ 66.2
มัธยฐาน62.6
ช่วง 90% กลาง52.4–70.0
จำนวนข้อมูล400
ดูข้อมูลเป็นตาราง (5 แถว)
ECDF จาก 400 ค่า มัธยฐาน 62.6
ควอนไทล์ค่า
5%52.4
25%58.3
50%62.6
75%66.2
95%70.0

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

  • สังเกตอะไร: ดูจุดที่ทำเครื่องหมายไว้ที่ 25, 50 และ 75 เปอร์เซ็นต์ จะเห็นว่าอ่านเปอร์เซ็นไทล์ได้ตรง ๆ ซึ่งฮิสโทแกรมทำไม่ได้เลย

ข้อควรระวัง

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

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

  • ผู้อ่านทั่วไปที่ไม่คุ้นกับกราฟสะสมใช้แทน: histogram หรือ density-plot
  • ต้องการเห็นยอดของการกระจายชัด ๆใช้แทน: histogram หรือ density-plot
  • ต้องเทียบหลายกลุ่มพร้อมกันเกิน 3 กลุ่มใช้แทน: box-plot หรือ ridgeline-plot

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

เทคนิคถัดไป · กราฟควอนไทล์เทียบควอนไทล์