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

เทเบิลพล็อตTableplot

ดูข้อมูลเป็นล้านแถวได้ในภาพเดียว

4
ขั้นสูงควรรู้ก่อน · เข้าใจว่าการยุบข้อมูลทำให้เสียรายละเอียด
ลองเล่น

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

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

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

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

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

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

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

ตัวอย่างคลาสสิก · Tableplot ในการสำรวจข้อมูลสำมะโนขนาดใหญ่

Tennekes และ de Jonge จากสำนักงานสถิติเนเธอร์แลนด์พัฒนา tableplot ขึ้นเพื่อตรวจคุณภาพข้อมูลสำมะโนที่มีหลายล้านแถว โดยพบว่าภาพนี้เผยปัญหาค่าที่หายไปแบบมีรูปแบบ ซึ่งการสุ่มตัวอย่างมาตรวจมักมองข้าม

Wikipedia · Exploratory data analysis

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

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

Tableplot แก้ด้วยการยุบแถวแทนที่จะสุ่ม โดยเรียงข้อมูลตามคอลัมน์หนึ่ง แล้วแบ่งเป็นกลุ่มละเท่า ๆ กันประมาณร้อยกลุ่ม จากนั้นสรุปค่าของทุกคอลัมน์ในแต่ละกลุ่ม

สิ่งที่ได้คือภาพที่ทุกคอลัมน์ใช้ลำดับแถวเดียวกัน ทำให้เห็นทันทีว่าเมื่อคอลัมน์ที่ใช้เรียงเพิ่มขึ้น คอลัมน์อื่นเปลี่ยนไปอย่างไรบ้าง

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

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

ข้อที่สองคือคอลัมน์ที่เลือกใช้เรียงเปลี่ยนภาพทั้งหมด ความสัมพันธ์ที่เห็นเป็นความสัมพันธ์กับคอลัมน์นั้นเท่านั้น และการเปลี่ยนคอลัมน์ที่ใช้เรียงก็เท่ากับเปลี่ยนคำถามที่ถาม

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

รูปทรงของข้อมูลตารางแบบกว้าง (หนึ่งแถวหนึ่ง entity)
จำนวนมิติที่เข้ารหัสได้4 มิติ
จำนวนแถวที่เหมาะ1,000–10,000,000 แถวขั้นต่ำ 30 แถว
เส้นฐานศูนย์ต้องเริ่มที่ศูนย์แต่ละคอลัมน์แสดงเป็นแถบ ซึ่งต้องเริ่มจากศูนย์

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

คอลัมน์ทำหน้าที่ชนิดเข้ารหัสด้วยจำนวนค่าที่เหมาะหมายเหตุ
item
ไม่บังคับ
ตัวระบุแถวหมวดหมู่text100–10,000,000 แถวไม่ได้แสดงในภาพ
group
ไม่บังคับ
กลุ่มหมวดหมู่color2–8 กลุ่มแสดงเป็นสัดส่วนในแต่ละแถบ
ราคาคอลัมน์ที่ใช้เรียงตัวเลขต่อเนื่องorderต่อเนื่อง★ การเลือกคอลัมน์นี้เปลี่ยนภาพทั้งหมด

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

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

ค่าที่หายไป — ★ จุดแข็งของภาพนี้คือค่าที่หายไปจะเห็นเป็นแถบชัดเจน จึงต้องแสดงให้เห็นไม่ใช่ซ่อน

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

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

น้อยกว่า 200 แถว การยุบเป็นกลุ่มไม่ช่วยอะไรและตารางธรรมดาอ่านง่ายกว่า

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

item,group,ราคา,ความเร็ว,ความจุ,น้ำหนัก,คะแนนรีวิว
รุ่น A,รุ่นประหยัด,167,48.5,17.6,30.9,3.17
รุ่น B,รุ่นมาตรฐาน,301,55.7,30.4,20,4.09

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

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

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

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

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

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

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

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

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

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

  • ไม่ระบุคอลัมน์ที่ใช้เรียง
  • ซ่อนค่าที่หายไป
  • ไม่เขียนช่วงค่ากำกับแต่ละคอลัมน์
  • ใช้กับข้อมูลน้อยเกินไป

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

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

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

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

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

ข้อมูล <จำนวน> แถว เรียงตาม <คอลัมน์> และยุบเป็น <จำนวน> กลุ่ม

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

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

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

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

df = pd.read_csv("tableplot-sample.csv")
df["ราคา"] = pd.to_numeric(df["ราคา"], errors="coerce")
df["ความเร็ว"] = pd.to_numeric(df["ความเร็ว"], errors="coerce")
df["ความจุ"] = pd.to_numeric(df["ความจุ"], errors="coerce")
df["น้ำหนัก"] = pd.to_numeric(df["น้ำหนัก"], errors="coerce")
df["คะแนนรีวิว"] = pd.to_numeric(df["คะแนนรีวิว"], errors="coerce")
NOTE = "sortcol"   # ← ค่าจาก Playground

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

dims = ["ราคา", "ความเร็ว", "ความจุ", "น้ำหนัก"]
SORT_BY, BINS = "ราคา", 10                          # ★ คอลัมน์ที่เรียงเปลี่ยนภาพทั้งหมด
d = df.sort_values(SORT_BY, ascending=False).reset_index(drop=True)
d["bin"] = (d.index * BINS // len(d))
agg = d.groupby("bin")[dims].mean()
fig, axes = plt.subplots(1, len(dims), figsize=(11, 5), sharey=True,
                         constrained_layout=True)
for ax_, dim in zip(axes, dims):
    ax_.barh(agg.index, agg[dim], color=C1, height=0.86)
    ax_.set_title(f"{dim}\n{agg[dim].min():.0f}–{agg[dim].max():.0f}", fontsize=9)
    ax_.invert_yaxis(); ax_.set_xticks([])
axes[0].set_ylabel(f"กลุ่ม (เรียงตาม {SORT_BY})")

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

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

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

ข้อมูลตัวอย่าง · 12 แถว · seed 197● คำนวณใหม่ในเบราว์เซอร์ทันทีที่ปรับค่า
คอลัมน์แรกคือคอลัมน์ที่เรียง
ราคาความเร็วความจุน้ำหนัก010%ราคา · กลุ่มที่ 1 · เฉลี่ย 426ความเร็ว · กลุ่มที่ 1 · เฉลี่ย 73.5ความจุ · กลุ่มที่ 1 · เฉลี่ย 42.5น้ำหนัก · กลุ่มที่ 1 · เฉลี่ย 17.61020%ราคา · กลุ่มที่ 2 · เฉลี่ย 395ความเร็ว · กลุ่มที่ 2 · เฉลี่ย 76.8ความจุ · กลุ่มที่ 2 · เฉลี่ย 43.9น้ำหนัก · กลุ่มที่ 2 · เฉลี่ย 17.72030%ราคา · กลุ่มที่ 3 · เฉลี่ย 306ความเร็ว · กลุ่มที่ 3 · เฉลี่ย 58.7ความจุ · กลุ่มที่ 3 · เฉลี่ย 34.7น้ำหนัก · กลุ่มที่ 3 · เฉลี่ย 22.73040%ราคา · กลุ่มที่ 4 · เฉลี่ย 302ความเร็ว · กลุ่มที่ 4 · เฉลี่ย 52.5ความจุ · กลุ่มที่ 4 · เฉลี่ย 27.3น้ำหนัก · กลุ่มที่ 4 · เฉลี่ย 23.04050%ราคา · กลุ่มที่ 5 · เฉลี่ย 191ความเร็ว · กลุ่มที่ 5 · เฉลี่ย 40.5ความจุ · กลุ่มที่ 5 · เฉลี่ย 20.2น้ำหนัก · กลุ่มที่ 5 · เฉลี่ย 29.85060%ราคา · กลุ่มที่ 6 · เฉลี่ย 170ความเร็ว · กลุ่มที่ 6 · เฉลี่ย 43.8ความจุ · กลุ่มที่ 6 · เฉลี่ย 18.7น้ำหนัก · กลุ่มที่ 6 · เฉลี่ย 29.2เรียงตาม ราคา จากมากไปน้อย แล้วแบ่งเป็น 10 กลุ่มเท่า ๆ กัน
จำนวนแถวทั้งหมด12
เรียงตามราคา
จำนวนกลุ่ม10
ดูข้อมูลเป็นตาราง (10 แถว)
tableplot 4 คอลัมน์ จาก 12 แถว
กลุ่มราคาความเร็วความจุน้ำหนัก
0–10%42673.542.517.6
10–20%39576.843.917.7
20–30%30658.734.722.7
30–40%30252.527.323.0
40–50%19140.520.229.8
50–60%17043.818.729.2
60–70%
70–80%
80–90%
90–100%

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

  • สังเกตอะไร: ลองจินตนาการว่าเปลี่ยนไปเรียงด้วยคอลัมน์อื่น ภาพทั้งภาพจะเปลี่ยนไปเลย เพราะคำถามที่ถามก็เปลี่ยนไปด้วย

ข้อควรระวัง

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

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

  • มีข้อมูลน้อยกว่า 200 แถวใช้แทน: scatter-matrix หรือตารางธรรมดา
  • ต้องหาค่าผิดปกติรายแถวใช้แทน: scatter-plot หรือ box-plot
  • สนใจความสัมพันธ์ระหว่างทุกคู่ตัวแปรใช้แทน: correlation-heatmap

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

เทคนิคถัดไป · พิกัดดาว