01ภาพรวมของกราฟนี้
Scatter plot วางข้อมูลแต่ละแถวเป็นจุดเดียวโดยใช้ตัวแปรหนึ่งเป็นแกนนอนและอีกตัวเป็นแกนตั้ง สิ่งที่อ่านได้ไม่ใช่ค่าของจุดใดจุดหนึ่ง แต่คือ "รูปแบบของกลุ่มจุดทั้งหมด" ซึ่งบอกทิศทาง ความแรง รูปร่าง และจุดที่หลุดออกไปในภาพเดียว
เปรียบเทียบให้เห็นภาพ
เหมือนโปรยเมล็ดถั่วลงบนกระดาษที่มีเส้นกริด ถ้าเมล็ดเรียงเป็นแนวเฉียง แปลว่าสองสิ่งที่วัดมีความเกี่ยวข้องกัน
ใช้ที่ไหนบ้าง — ดูว่างบโฆษณาสัมพันธ์กับยอดขายไหม ขนาดบ้านสัมพันธ์กับราคาไหม หรือหาความสัมพันธ์ก่อนสร้างโมเดล
สร้างอย่างไร
- ขั้นที่ 1เลือกตัวแปรสองตัว วางตัวที่คิดว่ามาก่อนไว้แกนนอน
- ขั้นที่ 2วาดจุดหนึ่งจุดต่อหนึ่งแถว
- ขั้นที่ 3ปรับความโปร่งใสถ้าจุดทับกัน
- ขั้นที่ 4ทำเครื่องหมายจุดที่จะพูดถึง
ตัวอย่างคลาสสิก · Anscombe’s Quartet — สี่ชุดข้อมูลที่สถิติเหมือนกันแต่หน้าตาคนละเรื่อง
Francis Anscombe สร้างชุดข้อมูลสี่ชุดในปี 1973 ที่มีค่าเฉลี่ย ความแปรปรวน สหสัมพันธ์ และเส้นถดถอยเท่ากันทุกตัว แต่เมื่อวาดเป็น scatter plot กลับพบว่าชุดหนึ่งเป็นเส้นตรง ชุดหนึ่งโค้ง ชุดหนึ่งมีค่าผิดปกติหนึ่งจุด และอีกชุดเป็นเส้นตั้ง นี่คือข้อโต้แย้งที่ทรงพลังที่สุดว่าทำไมต้องวาดกราฟก่อนเชื่อตัวเลขสรุป
02อธิบายภาษาคนเข้าใจง่าย ๆ
เมื่ออยากรู้ว่าสองสิ่งเกี่ยวข้องกันไหม เช่น เวลาอ่านหนังสือกับคะแนนสอบ วิธีที่ตรงที่สุดคือวางทั้งสองค่าของนักเรียนแต่ละคนเป็นจุดเดียวบนแผนภาพ
ทันทีที่วางครบทุกคน รูปแบบของกลุ่มจุดจะบอกเรื่องสี่อย่างพร้อมกัน คือทิศทางว่าขึ้นหรือลง ความแรงว่าจุดเกาะแนวแน่นแค่ไหน รูปร่างว่าเป็นเส้นตรงหรือโค้ง และมีใครหลุดออกไปไหม
สิ่งที่สำคัญที่สุดและคนพลาดบ่อยที่สุดคือ กราฟนี้บอกได้แค่ว่าสองสิ่งขยับไปด้วยกัน ไม่ได้บอกว่าอะไรเป็นเหตุของอะไร ยอดขายไอศกรีมกับจำนวนคนจมน้ำขยับไปด้วยกัน แต่ไอศกรีมไม่ได้ทำให้คนจมน้ำ อากาศร้อนต่างหากที่ทำให้ทั้งสองเพิ่ม
เมื่อจุดเยอะขึ้น ปัญหาใหม่คือจุดทับกันจนบริเวณที่หนาแน่นดูเหมือนมีข้อมูลน้อย ทางแก้คือลดความทึบของจุด หรือเมื่อเกินไม่กี่พันจุดก็ต้องเปลี่ยนไปใช้ hexbin ที่นับความหนาแน่นให้
เรื่องสีมีข้อจำกัดที่ต้องรู้ เพราะจุดของทุกกลุ่มปนกันอยู่บนพื้นที่เดียว การแยกสีจึงยากกว่ากราฟแท่งมาก ในทางปฏิบัติจำกัดไว้ที่ 3 สี เกินกว่านั้นต้องแยกเป็นกราฟย่อยหลายอัน
03ข้อมูลที่ต้องใช้
คอลัมน์ที่ต้องเตรียม
| คอลัมน์ | ทำหน้าที่ | ชนิด | เข้ารหัสด้วย | จำนวนค่าที่เหมาะ | หมายเหตุ |
|---|---|---|---|---|---|
x | ตัวแปรที่คิดว่ามาก่อน | ตัวเลขต่อเนื่อง | x | ต่อเนื่อง | วางตัวแปรที่เราควบคุมหรือคิดว่าเป็นเหตุไว้แกนนอน |
y | ตัวแปรที่อยากอธิบาย | ตัวเลขต่อเนื่อง | y | ต่อเนื่อง | ตัวแปรที่เป็นผลลัพธ์ |
groupไม่บังคับ | กลุ่ม | หมวดหมู่ | color | <= 3 กลุ่ม | ★ เกิน 3 กลุ่มให้แยกเป็น small multiples เพราะจุดปนกันจนแยกสีไม่ออก |
ต้องเตรียมข้อมูลอย่างไรก่อนวาด
- ตัดแถวที่ x หรือ y ว่างออก ต้องครบทั้งคู่ถึงจะวาดจุดได้
- ตรวจค่าซ้ำที่ทับกันสนิท ถ้ามีมากให้ใส่ jitter เล็กน้อยหรือใช้ opacity
- ถ้าหน่วยต่างกันมากจนจุดเกาะขอบ พิจารณา log ทีละแกน
ค่าที่หายไป — ตัดเฉพาะแถวที่ขาด x หรือ y และรายงานจำนวน — ห้ามเติมค่าเฉลี่ยแทน เพราะจะสร้างกระจุกปลอมกลางภาพ
สเกลของแกน — ใช้ linear ทั้งสองแกนเป็นค่าเริ่มต้น ใช้ log เมื่อข้อมูลกินหลาย order of magnitude
กราฟจะเริ่มพังเมื่อไร
เกิน 5,000 จุด จะทับกันจนอ่านความหนาแน่นไม่ได้ — เปลี่ยนไปใช้ hexbin-plot หรือ contour-plot
หน้าตาไฟล์ที่ต้องเตรียม
x,y,group
…04อ่านแล้วเห็นอะไร
สิ่งที่เห็นได้จากภาพ
- ทิศทาง — ขึ้น ลง หรือไม่มีทิศทาง
- ความแรง — จุดเกาะกันแน่นรอบแนวเส้นหรือกระจายเป็นเมฆ
- รูปร่าง — เป็นเส้นตรง โค้ง หรือหักที่ค่าหนึ่ง
- กลุ่มก้อนที่แยกออกจากกัน ซึ่งมักแปลว่ามีกลุ่มย่อยซ่อนอยู่
- จุดที่หลุดออกไปไกล ซึ่งอาจเป็นข้อผิดพลาดหรือเป็นกรณีที่น่าสนใจที่สุด
สิ่งที่กราฟนี้ตอบไม่ได้
- ★ บอกไม่ได้ว่าอะไรเป็นเหตุของอะไร — ความสัมพันธ์ไม่ใช่เหตุและผล นี่คือข้อผิดพลาดที่คนทำบ่อยที่สุดกับกราฟนี้
- ไม่บอกว่ามีตัวแปรที่สามซ่อนอยู่ที่อธิบายทั้งคู่หรือไม่
- ไม่บอกความหนาแน่นที่แท้จริงเมื่อจุดทับกัน
- ไม่บอกลำดับเวลา เว้นแต่จะเปลี่ยนไปใช้ connected-scatter
อ่านตามลำดับนี้
- ดูทิศทางรวมของกลุ่มจุดก่อน
- ดูว่าจุดเกาะแนวแน่นหรือกระจาย
- หาจุดที่หลุดออกไปจากกลุ่ม
- ตรวจว่าแกนทั้งสองเริ่มที่เท่าไร
คำถามที่ตอบได้
- สองตัวแปรนี้เกี่ยวข้องกันไหม
- ความสัมพันธ์เป็นเส้นตรงหรือโค้ง
- มีข้อมูลที่ผิดปกติไหม
สัญญาณว่ามีอะไรผิด
- จุดเรียงเป็นเส้นตรงเป๊ะเกินไป มักแปลว่าสองคอลัมน์คำนวณมาจากกันเอง
- จุดเรียงเป็นตารางกริด แปลว่าข้อมูลถูกปัดค่ามาก่อน
- กลุ่มจุดที่ค่าเดียวกันเป๊ะจำนวนมาก มักเป็นค่า default ที่ระบบเติมให้
05เหมาะกับการนำเสนอแบบไหน
ทำอย่างไรให้คนอ่านได้ข้อสรุปโดยไม่ต้องบรรยาย
- วงกลมหรือติดป้ายเฉพาะจุดที่จะพูดถึง อย่าติดป้ายทุกจุด
- ถ้าจะใส่เส้นแนวโน้ม ต้องบอกว่าเป็นเส้นแบบไหนและ R² เท่าไร
- เขียนหน่วยของทั้งสองแกนให้ชัด
- ถ้าตัดแกนไม่เริ่มที่ศูนย์ ให้ระบุไว้ในแกนหรือ caption
รูปแบบชื่อกราฟที่ควรใช้
เมื่อ <x> เพิ่มขึ้น <y> มีแนวโน้ม <เพิ่ม/ลด> — แต่ยังมี <ข้อยกเว้น>
06เอาไปใช้ต่อ
โค้ดทุกชิ้นอ่านไฟล์ scatter-plot-sample.csv ชุดเดียวกับที่ Playground ใช้ และตัวเลขในโค้ดเปลี่ยนตามค่าที่คุณปรับด้านล่าง
# ติดตั้ง: pip install "matplotlib==3.10.*" "pandas==2.*"
# ดาวน์โหลด scatter-plot-sample.csv จากหน้านี้ แล้ววางไว้ข้างสคริปต์
import matplotlib
matplotlib.use("Agg") # รันแบบไม่มีหน้าจอ ถ้ารันในเครื่องตัวเองลบบรรทัดนี้ได้
import matplotlib.pyplot as plt
import pandas as pd
C1, C2, C3 = "#2a78d6", "#eb6834", "#1baf7a" # palette ของคลัง เปลี่ยนเป็นสีองค์กรได้
INK, SURFACE = "#0b0b0b", "#fcfcfb"
df = pd.read_csv("scatter-plot-sample.csv")
df["x"] = pd.to_numeric(df["x"], errors="coerce")
df["y"] = pd.to_numeric(df["y"], errors="coerce")
OPACITY = 0.75 # ← ค่าจาก Playground
fig, ax = plt.subplots(figsize=(7.6, 4.2), facecolor=SURFACE)
ax.set_facecolor(SURFACE)
d = df.dropna(subset=["x", "y"])
for i, (g, sub) in enumerate(d.groupby("group")):
ax.scatter(sub["x"], sub["y"], s=34, alpha=OPACITY, color=[C1, C2, C3][i % 3],
edgecolor=SURFACE, linewidth=0.8, label=g)
ax.set_xlabel("ตัวแปรที่คิดว่ามาก่อน (x)"); ax.set_ylabel("ตัวแปรที่อยากอธิบาย (y)")
ax.legend(frameon=False, title="กลุ่ม")
r = d["x"].corr(d["y"])
ax.set_title(f"r = {r:.3f} · ความสัมพันธ์ไม่ใช่เหตุและผล", loc="left", fontsize=10)
ax.spines[["top", "right"]].set_visible(False) # ลดเส้นที่ไม่ได้ให้ข้อมูล
fig.tight_layout()
fig.savefig("scatter-plot.png", dpi=160)
print("เขียน scatter-plot.png แล้ว ·", len(df), "แถว")07ลองเล่นเพื่อเข้าใจ
ค่า r บอกได้แค่ว่าสองสิ่งขยับไปด้วยกัน ไม่ได้บอกว่าอะไรเป็นเหตุของอะไร
ดูข้อมูลเป็นตาราง (40 แถว)
| x | y | กลุ่ม |
|---|---|---|
| 20.0 | 45.0 | กลุ่มเมือง |
| 13.1 | 32.1 | กลุ่มชานเมือง |
| 20.8 | 39.0 | กลุ่มต่างจังหวัด |
| 36.4 | 59.6 | กลุ่มเมือง |
| 18.7 | 29.9 | กลุ่มชานเมือง |
| 28.3 | 34.9 | กลุ่มต่างจังหวัด |
| 46.7 | 62.8 | กลุ่มเมือง |
| 24.8 | 48.6 | กลุ่มชานเมือง |
| 45.9 | 55.7 | กลุ่มต่างจังหวัด |
| 24.6 | 40.1 | กลุ่มเมือง |
| 22.6 | 37.5 | กลุ่มชานเมือง |
| 48.8 | 54.1 | กลุ่มต่างจังหวัด |
| 13.2 | 32.3 | กลุ่มเมือง |
| 24.9 | 49.0 | กลุ่มชานเมือง |
| 57.8 | 63.1 | กลุ่มต่างจังหวัด |
| 21.9 | 39.4 | กลุ่มเมือง |
| 41.2 | 65.8 | กลุ่มชานเมือง |
| 35.1 | 42.0 | กลุ่มต่างจังหวัด |
| 10.8 | 32.6 | กลุ่มเมือง |
| 13.5 | 34.5 | กลุ่มชานเมือง |
| 43.7 | 50.0 | กลุ่มต่างจังหวัด |
| 30.3 | 49.1 | กลุ่มเมือง |
| 21.3 | 35.1 | กลุ่มชานเมือง |
| 43.1 | 48.7 | กลุ่มต่างจังหวัด |
| 8.02 | 21.9 | กลุ่มเมือง |
| 24.5 | 45.8 | กลุ่มชานเมือง |
| 52.6 | 61.3 | กลุ่มต่างจังหวัด |
| 24.5 | 47.8 | กลุ่มเมือง |
| 22.9 | 40.9 | กลุ่มชานเมือง |
| 33.2 | 41.5 | กลุ่มต่างจังหวัด |
| 45.5 | 64.9 | กลุ่มเมือง |
| 45.7 | 64.2 | กลุ่มชานเมือง |
| 30.7 | 42.8 | กลุ่มต่างจังหวัด |
| 17.0 | 34.3 | กลุ่มเมือง |
| 30.5 | 44.8 | กลุ่มชานเมือง |
| 37.2 | 48.3 | กลุ่มต่างจังหวัด |
| 23.6 | 43.0 | กลุ่มเมือง |
| 36.5 | 55.4 | กลุ่มชานเมือง |
| 47.9 | 61.6 | กลุ่มต่างจังหวัด |
| 10.4 | 33.7 | กลุ่มเมือง |
ลองแล้วจะเห็นอะไร
- ความทึบของจุด: ลดความทึบลงแล้วสังเกตว่าบริเวณที่จุดซ้อนกันหลายชั้นจะเข้มขึ้น ทำให้เห็นความหนาแน่นที่จุดทึบเต็มที่กลบไว้
ข้อควรระวัง
- ★ ตีความว่าเป็นเหตุและผล ทั้งที่กราฟบอกได้แค่ว่าสองสิ่งขยับไปด้วยกัน
- จุดทับกันจนดูเหมือนข้อมูลน้อยกว่าความจริง — แก้ด้วย opacity, jitter หรือเปลี่ยนไป hexbin
- ใส่เส้นแนวโน้มเชิงเส้นกับข้อมูลที่ชัดเจนว่าโค้ง
- ใช้สีเกิน 3 กลุ่ม ทำให้คนตาบอดสีแยกไม่ออกเลย
- ตัดแกนโดยไม่บอก ทำให้ความสัมพันธ์ดูแรงกว่าความจริง
เมื่อไหร่ไม่ควรใช้กราฟนี้
- มีจุดมากกว่า 5,000 จุด→ใช้แทน: hexbin-plot หรือ contour-plot
- ตัวแปรหนึ่งเป็นหมวดหมู่→ใช้แทน: box-plot หรือ strip-plot
- ข้อมูลเรียงตามเวลาและลำดับสำคัญ→ใช้แทน: connected-scatter
- ต้องเทียบมากกว่าสองตัวแปร→ใช้แทน: scatter-matrix หรือ bubble-chart