01ภาพรวมของกราฟนี้
Parallel coordinates วางแกนของแต่ละตัวแปรขนานกันในแนวตั้ง แล้วลากเส้นเชื่อมค่าของแถวเดียวกัน จุดแข็งเหนือวิธีลดมิติคือยังอ่านค่าจริงของทุกตัวแปรได้ และเห็นความสัมพันธ์ระหว่างแกนที่ติดกันจากรูปแบบของเส้น
เปรียบเทียบให้เห็นภาพ
เหมือนตารางที่แต่ละคอลัมน์ตั้งขึ้นเป็นแกน แล้วลากเส้นเชื่อมค่าของคนเดียวกันข้ามคอลัมน์
ใช้ที่ไหนบ้าง — เปรียบเทียบสินค้าหลายรุ่นด้วยหลายคุณสมบัติ กรองข้อมูลหลายเงื่อนไขพร้อมกัน หรือหากลุ่มในข้อมูลหลายมิติ
สร้างอย่างไร
- ขั้นที่ 1เลือกตัวแปรและจัดลำดับแกน
- ขั้นที่ 2ปรับสเกลของแต่ละแกนให้เต็มความสูง
- ขั้นที่ 3ลากเส้นเชื่อมค่าของแต่ละแถว
- ขั้นที่ 4ระบายสีตามกลุ่มหรือตามค่าของตัวแปรหลัก
ตัวอย่างคลาสสิก · Alfred Inselberg พัฒนาระบบพิกัดขนานในทศวรรษ 1980
Inselberg ศึกษาคุณสมบัติทางเรขาคณิตของการแทนจุดในปริภูมิหลายมิติด้วยเส้นบนแกนขนาน และพบว่ารูปแบบบางอย่างมีความหมายทางคณิตศาสตร์ เช่น จุดที่อยู่บนเส้นตรงในปริภูมิหลายมิติจะให้เส้นที่ตัดกันที่จุดเดียวกัน ซึ่งทำให้วิธีนี้ไม่ใช่แค่การจัดวางที่สวยงามแต่มีฐานทางทฤษฎี
02อธิบายภาษาคนเข้าใจง่าย ๆ
ข้อมูลที่มี 5-6 ตัวแปรวาดบนระนาบสองมิติตรง ๆ ไม่ได้ วิธีหนึ่งคือลดมิติด้วย PCA แต่นั่นทำให้อ่านค่าของตัวแปรเดิมไม่ได้อีกเลย
Parallel coordinates ใช้วิธีตรงกว่า คือตั้งแกนของแต่ละตัวแปรขนานกัน แล้วลากเส้นเชื่อมค่าของแถวเดียวกันข้ามทุกแกน หนึ่งเส้นคือหนึ่งแถว
ข้อดีที่ชัดคือยังอ่านค่าจริงได้ ถ้าอยากรู้ว่าสินค้ารุ่นนี้ราคาเท่าไร ก็ดูว่าเส้นของมันตัดแกนราคาที่ตำแหน่งไหน
รูปแบบที่อ่านได้คือความสัมพันธ์ระหว่างแกนที่ติดกัน ถ้าเส้นส่วนใหญ่ลาดลงจากแกนหนึ่งไปอีกแกน แปลว่าสองตัวแปรนั้นสัมพันธ์กันแบบผกผัน ถ้าเส้นตัดกันไขว้ไปมาก็แปลว่าไม่สัมพันธ์
ข้อจำกัดใหญ่คือความสัมพันธ์เห็นได้เฉพาะแกนที่อยู่ติดกัน การจัดลำดับแกนจึงเป็นการตัดสินใจที่กระทบข้อสรุปโดยตรง และควรลองหลายลำดับก่อนสรุป
03ข้อมูลที่ต้องใช้
คอลัมน์ที่ต้องเตรียม
| คอลัมน์ | ทำหน้าที่ | ชนิด | เข้ารหัสด้วย | จำนวนค่าที่เหมาะ | หมายเหตุ |
|---|---|---|---|---|---|
ราคา | ตัวแปรที่ 1 | ตัวเลขต่อเนื่อง | y | ต่อเนื่อง | แต่ละคอลัมน์ตัวเลขกลายเป็นหนึ่งแกน |
ความเร็ว | ตัวแปรที่ 2 | ตัวเลขต่อเนื่อง | y | ต่อเนื่อง | ควรมี 3–8 แกน |
groupไม่บังคับ | กลุ่ม | หมวดหมู่ | color | <= 8 กลุ่ม | ใช้ระบายสีเพื่อดูว่ากลุ่มแยกกันไหม |
ต้องเตรียมข้อมูลอย่างไรก่อนวาด
- ★ ปรับสเกลของแต่ละแกนให้เต็มความสูงแยกกัน เพราะหน่วยต่างกัน
- ตัดสินใจลำดับของแกนและลองหลายลำดับ
- ตัดแถวที่ขาดค่าใดค่าหนึ่ง
ค่าที่หายไป — แถวที่ขาดค่าใดค่าหนึ่งลากเส้นไม่ครบ ต้องตัดออกและรายงาน หรือทำเครื่องหมายเส้นที่ขาดให้ต่างออกไป
สเกลของแกน — แต่ละแกนใช้สเกลของตัวเองเต็มความสูง และต้องเขียนค่าต่ำสุดกับสูงสุดกำกับที่ปลายแกน
กราฟจะเริ่มพังเมื่อไร
เกิน 300 เส้น ภาพจะกลายเป็นก้อนทึบ — ใช้ความโปร่งใสหรือกรองข้อมูลก่อน
หน้าตาไฟล์ที่ต้องเตรียม
item,group,ราคา,ความเร็ว,ความจุ,น้ำหนัก,คะแนนรีวิว
รุ่น A,รุ่นประหยัด,167,48.5,17.6,30.9,3.17
รุ่น B,รุ่นมาตรฐาน,301,55.7,30.4,20,4.09
…04อ่านแล้วเห็นอะไร
สิ่งที่เห็นได้จากภาพ
- ความสัมพันธ์ระหว่างแกนที่ติดกันจากทิศของเส้น
- กลุ่มของเส้นที่เดินทางไปด้วยกัน
- เส้นที่แยกตัวออกไปซึ่งคือแถวที่ผิดปกติ
- แกนที่แยกกลุ่มได้ดีที่สุด
สิ่งที่กราฟนี้ตอบไม่ได้
- ★ ความสัมพันธ์เห็นได้เฉพาะแกนที่อยู่ติดกัน ถ้าจะดูคู่อื่นต้องสลับลำดับแกน
- เมื่อเส้นเยอะจะทับกันจนอ่านรายเส้นไม่ได้
อ่านตามลำดับนี้
- เลือกเส้นหนึ่งเส้นแล้วตามจากแกนซ้ายไปขวา
- ดูว่าเส้นระหว่างสองแกนขนานกันหรือไขว้กัน
- หากลุ่มของเส้นที่เดินทางคล้ายกัน
คำถามที่ตอบได้
- รายการนี้มีค่าเท่าไรในแต่ละตัวแปร
- ตัวแปรสองตัวนี้สัมพันธ์กันไหม
- มีกลุ่มที่มีรูปแบบชัดเจนไหม
สัญญาณว่ามีอะไรผิด
- ไม่เขียนค่าต่ำสุดและสูงสุดที่ปลายแกน ทำให้อ่านค่าไม่ได้
- เส้นทับกันจนเป็นก้อนทึบ
- ไม่บอกว่าใช้ลำดับแกนแบบไหน
05เหมาะกับการนำเสนอแบบไหน
ทำอย่างไรให้คนอ่านได้ข้อสรุปโดยไม่ต้องบรรยาย
- เขียนค่าต่ำสุดและสูงสุดที่ปลายแกนทุกแกน
- ใช้ความโปร่งใสเมื่อเส้นเยอะ
- เน้นเส้นที่เป็นประเด็นและทำเส้นอื่นเป็นสีเทา
รูปแบบชื่อกราฟที่ควรใช้
รายการที่ <คุณสมบัติ> สูง มักมี <คุณสมบัติ> ต่ำด้วย
06เอาไปใช้ต่อ
โค้ดทุกชิ้นอ่านไฟล์ parallel-coordinates-sample.csv ชุดเดียวกับที่ Playground ใช้ และตัวเลขในโค้ดเปลี่ยนตามค่าที่คุณปรับด้านล่าง
# ติดตั้ง: pip install "matplotlib==3.10.*" "pandas==2.*"
# ดาวน์โหลด parallel-coordinates-sample.csv จากหน้านี้ แล้ววางไว้ข้างสคริปต์
import matplotlib
matplotlib.use("Agg") # รันแบบไม่มีหน้าจอ ถ้ารันในเครื่องตัวเองลบบรรทัดนี้ได้
import matplotlib.pyplot as plt
import pandas as pd
from pandas.plotting import parallel_coordinates
C1, C2, C3 = "#2a78d6", "#eb6834", "#1baf7a" # palette ของคลัง เปลี่ยนเป็นสีองค์กรได้
INK, SURFACE = "#0b0b0b", "#fcfcfb"
df = pd.read_csv("parallel-coordinates-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 = "adjacent" # ← ค่าจาก Playground
fig, ax = plt.subplots(figsize=(7.6, 4.2), facecolor=SURFACE)
ax.set_facecolor(SURFACE)
cols = ["ราคา", "ความเร็ว", "ความจุ", "น้ำหนัก", "คะแนนรีวิว"]
scaled = df.copy()
for c in cols: # ★ ปรับสเกลแต่ละแกนให้เต็มความสูง
scaled[c] = (df[c] - df[c].min()) / (df[c].max() - df[c].min())
parallel_coordinates(scaled[cols + ["group"]], "group", ax=ax,
color=[C1, C2, C3], alpha=0.55, linewidth=1.6)
for i, c in enumerate(cols): # เขียนค่าจริงที่ปลายแกน
ax.text(i, 1.04, f"{df[c].max():,.0f}", ha="center", fontsize=8, color="#7a7872")
ax.text(i, -0.07, f"{df[c].min():,.0f}", ha="center", fontsize=8, color="#7a7872")
ax.set_yticks([]); ax.legend(frameon=False, title="กลุ่ม")
ax.spines[["top", "right"]].set_visible(False) # ลดเส้นที่ไม่ได้ให้ข้อมูล
fig.tight_layout()
fig.savefig("parallel-coordinates.png", dpi=160)
print("เขียน parallel-coordinates.png แล้ว ·", len(df), "แถว")07ลองเล่นเพื่อเข้าใจ
ลำดับของแกนเปลี่ยนรูปแบบที่มองเห็น — ความสัมพันธ์จะเห็นได้ก็ต่อเมื่อแกนสองแกนนั้นอยู่ติดกัน
ดูข้อมูลเป็นตาราง (18 แถว)
| รายการ | กลุ่ม | ราคา | ความเร็ว | ความจุ | น้ำหนัก | คะแนนรีวิว |
|---|---|---|---|---|---|---|
| รุ่น A | รุ่นประหยัด | 167 | 48.5 | 17.6 | 30.9 | 3.17 |
| รุ่น B | รุ่นมาตรฐาน | 301 | 55.7 | 30.4 | 20.0 | 4.09 |
| รุ่น C | รุ่นพรีเมียม | 393 | 76.1 | 43.6 | 17.2 | 4.14 |
| รุ่น D | รุ่นประหยัด | 195 | 38.2 | 21.9 | 29.5 | 3.20 |
| รุ่น E | รุ่นมาตรฐาน | 304 | 57.4 | 35.1 | 23.3 | 3.82 |
| รุ่น F | รุ่นพรีเมียม | 432 | 67.9 | 38.5 | 15.4 | 4.47 |
| รุ่น G | รุ่นประหยัด | 186 | 42.8 | 18.5 | 30.0 | 3.04 |
| รุ่น H | รุ่นมาตรฐาน | 302 | 49.3 | 24.1 | 25.9 | 3.67 |
| รุ่น I | รุ่นพรีเมียม | 396 | 77.5 | 44.1 | 18.2 | 4.41 |
| รุ่น J | รุ่นประหยัด | 173 | 39.0 | 19.7 | 27.5 | 3.50 |
| รุ่น K | รุ่นมาตรฐาน | 308 | 60.0 | 34.2 | 22.1 | 3.82 |
| รุ่น L | รุ่นพรีเมียม | 420 | 79.1 | 46.4 | 19.7 | 4.27 |
| รุ่น M | รุ่นประหยัด | 173 | 35.9 | 19.5 | 31.9 | 3.11 |
| รุ่น N | รุ่นมาตรฐาน | 298 | 64.6 | 32.6 | 23.0 | 3.65 |
| รุ่น O | รุ่นพรีเมียม | 435 | 77.7 | 41.1 | 17.8 | 4.00 |
| รุ่น P | รุ่นประหยัด | 196 | 43.2 | 19.5 | 29.6 | 3.23 |
| รุ่น Q | รุ่นมาตรฐาน | 296 | 55.8 | 34.5 | 23.3 | 3.81 |
| รุ่น R | รุ่นพรีเมียม | 422 | 74.4 | 45.8 | 16.8 | 4.17 |
ลองแล้วจะเห็นอะไร
- สังเกตอะไร: ดูช่วงระหว่างแกนที่ติดกันทีละช่วง ถ้าเส้นขนานกันแปลว่าสัมพันธ์กันทางบวก ถ้าไขว้กันเป็นรูปนาฬิกาทรายแปลว่าสัมพันธ์กันทางลบ
ข้อควรระวัง
- ไม่ปรับสเกลของแต่ละแกน ทำให้ตัวแปรที่หน่วยใหญ่ครองภาพทั้งหมด
- ลืมว่าความสัมพันธ์เห็นได้เฉพาะแกนที่ติดกัน แล้วสรุปว่าตัวแปรที่อยู่คนละฝั่งไม่สัมพันธ์กัน
- ใส่เส้นมากเกินไปจนเป็นก้อนทึบ
- ไม่เขียนค่าต่ำสุดและสูงสุดที่ปลายแกน ทำให้อ่านค่าจริงไม่ได้
เมื่อไหร่ไม่ควรใช้กราฟนี้
- มีตัวแปรน้อยกว่า 3 ตัว→ใช้แทน: scatter-plot
- มีมากกว่า 300 แถว→ใช้แทน: scatter-matrix หรือกรองข้อมูลก่อน
- ต้องการดูโครงสร้างกลุ่มโดยไม่สนค่าจริง→ใช้แทน: embedding-projection หรือ andrews-curves