01ภาพรวมของกราฟนี้
Contour map ลากเส้นเชื่อมจุดที่มีค่าเท่ากัน ทำให้อ่านค่าได้จากตัวเลขบนเส้นและอ่านความชันได้จากระยะห่างระหว่างเส้น ซึ่งเป็นสิ่งที่ heat map ทำไม่ได้ แลกกับการที่ต้องใช้กับปรากฏการณ์ที่ต่อเนื่องจริงเท่านั้น
เปรียบเทียบให้เห็นภาพ
เหมือนแผนที่ภูมิประเทศสำหรับเดินป่าที่เส้นชิดกันแปลว่าชัน และเส้นห่างกันแปลว่าที่ราบ
ใช้ที่ไหนบ้าง — ความสูงของภูมิประเทศ ความกดอากาศ ปริมาณน้ำฝน ระดับเสียงรบกวน หรือความเข้มข้นของมลพิษ
สร้างอย่างไร
- ขั้นที่ 1ตรวจว่าปรากฏการณ์ต่อเนื่องจริงในเชิงพื้นที่
- ขั้นที่ 2ประมาณค่าระหว่างจุดวัดด้วยวิธีที่เหมาะสม
- ขั้นที่ 3ลากเส้นที่ระดับค่าที่กำหนดพร้อมติดตัวเลข
- ขั้นที่ 4แสดงจุดวัดจริงทับเพื่อให้ตรวจสอบได้
ตัวอย่างคลาสสิก · แผนที่เส้นชั้นความสูงในการทำแผนที่ภูมิประเทศ
เส้นชั้นความสูงถูกใช้ในแผนที่ภูมิประเทศมาตั้งแต่คริสต์ศตวรรษที่ 18 และยังเป็นมาตรฐานถึงปัจจุบัน เพราะให้สิ่งที่การระบายสีให้ไม่ได้ คือค่าที่อ่านได้ตรง ๆ และความชันที่อ่านได้จากระยะห่างของเส้น ซึ่งนักเดินป่าใช้วางแผนเส้นทางจริง
02อธิบายภาษาคนเข้าใจง่าย ๆ
ปรากฏการณ์บางอย่างต่อเนื่องในพื้นที่จริง ๆ เช่น ความสูงของพื้นดินหรือความกดอากาศ ซึ่งมีค่าอยู่ทุกจุดไม่ว่าเราจะวัดหรือไม่
สำหรับข้อมูลแบบนี้ การระบายสีก็ทำได้ แต่สีอ่านค่าได้หยาบมาก ผู้อ่านบอกได้แค่ว่าเข้มกว่าหรืออ่อนกว่า และที่สำคัญคือบอกไม่ได้เลยว่าค่าเปลี่ยนเร็วแค่ไหนเมื่อเดินจากจุดหนึ่งไปอีกจุด
Contour map ลากเส้นเชื่อมจุดที่มีค่าเท่ากันแทน ซึ่งให้สองอย่างที่สีให้ไม่ได้ คือค่าที่อ่านได้ตรง ๆ จากตัวเลขบนเส้น และความชันที่อ่านได้จากระยะห่างระหว่างเส้น
เส้นที่ชิดกันแปลว่าค่าเปลี่ยนเร็วในระยะสั้น ส่วนเส้นที่ห่างกันแปลว่าค่าเปลี่ยนช้า ซึ่งเป็นข้อมูลที่มีค่ามากและอ่านได้ทันทีโดยไม่ต้องคำนวณ
ข้อจำกัดที่สำคัญคือมันใช้ได้เฉพาะกับปรากฏการณ์ที่ต่อเนื่องจริง การลากเส้นชั้นของรายได้เฉลี่ยหรือจำนวนประชากรเป็นความผิดพลาด เพราะค่าพวกนั้นไม่ได้มีอยู่ทุกจุดในพื้นที่
และเหมือนทุกภาพที่ประมาณค่าระหว่างจุดวัด พื้นที่ที่ไม่มีจุดวัดเลยก็ยังมีเส้นลากผ่าน ซึ่งเป็นการเดาที่ดูน่าเชื่อถือเกินจริง จึงควรแสดงจุดวัดจริงทับเสมอ
03ข้อมูลที่ต้องใช้
คอลัมน์ที่ต้องเตรียม
| คอลัมน์ | ทำหน้าที่ | ชนิด | เข้ารหัสด้วย | จำนวนค่าที่เหมาะ | หมายเหตุ |
|---|---|---|---|---|---|
lat | ละติจูด | เชิงพื้นที่ | y | ต่อเนื่อง | พิกัดของจุดวัด |
lon | ลองจิจูด | เชิงพื้นที่ | x | ต่อเนื่อง | ควรกระจายทั่วพื้นที่ |
value | ค่าที่วัดได้ | ตัวเลขต่อเนื่อง | color | ต่อเนื่อง | ★ ต้องเป็นปรากฏการณ์ที่ต่อเนื่องในพื้นที่จริง |
ต้องเตรียมข้อมูลอย่างไรก่อนวาด
- ★ ตรวจว่าปรากฏการณ์ต่อเนื่องจริง ไม่ใช่ข้อมูลรายเขต
- เลือกวิธีประมาณค่าระหว่างจุดและระบุไว้
- กำหนดระดับของเส้นให้ห่างเท่ากัน
ค่าที่หายไป — บริเวณที่อยู่นอกขอบเขตของจุดวัดไม่ควรลากเส้น และต้องตีกรอบให้ชัด
สเกลของแกน — ระดับของเส้นควรห่างเท่ากันเพื่อให้ระยะห่างระหว่างเส้นสื่อความชันได้ตรง
กราฟจะเริ่มพังเมื่อไร
จุดวัดกระจุกอยู่มุมเดียว ทำให้เส้นในบริเวณอื่นเป็นการเดาล้วน ๆ
หน้าตาไฟล์ที่ต้องเตรียม
lat,lon,value
13.8013,100.1331,184
18.2209,98.5482,50
…04อ่านแล้วเห็นอะไร
สิ่งที่เห็นได้จากภาพ
- ค่าที่ตำแหน่งใดก็ได้จากเส้นที่ผ่าน
- บริเวณที่ค่าเปลี่ยนเร็วซึ่งคือที่เส้นชิดกัน
- ยอดและแอ่งซึ่งคือวงปิดที่ซ้อนกัน
สิ่งที่กราฟนี้ตอบไม่ได้
- ★ ค่าในบริเวณที่ไม่มีจุดวัด ซึ่งเป็นการประมาณที่ดูน่าเชื่อถือเกินจริง
- รายละเอียดที่ละเอียดกว่าระยะห่างระหว่างจุดวัด
อ่านตามลำดับนี้
- หาตัวเลขบนเส้นเพื่อรู้ระดับ
- ดูระยะห่างระหว่างเส้นเพื่อรู้ความชัน
- มองหาวงปิดที่ซ้อนกันซึ่งคือยอดหรือแอ่ง
คำถามที่ตอบได้
- ที่ตำแหน่งนี้ค่าเท่าไร
- ตรงไหนที่ค่าเปลี่ยนเร็วที่สุด
- ยอดสูงสุดและแอ่งต่ำสุดอยู่ที่ไหน
สัญญาณว่ามีอะไรผิด
- ใช้กับข้อมูลที่ไม่ต่อเนื่อง เช่น รายได้รายเขต
- ลากเส้นในบริเวณที่ไม่มีจุดวัดเลย
- ระดับของเส้นห่างไม่เท่ากันโดยไม่ระบุ
05เหมาะกับการนำเสนอแบบไหน
ทำอย่างไรให้คนอ่านได้ข้อสรุปโดยไม่ต้องบรรยาย
- ★ ติดตัวเลขบนเส้นทุกเส้นหรือทุกเส้นที่สอง
- แสดงจุดวัดจริงทับเพื่อให้ตรวจสอบได้
- ระบายสีระหว่างเส้นเพิ่มเพื่อให้อ่านทิศทางง่ายขึ้น
รูปแบบชื่อกราฟที่ควรใช้
<ตัวชี้วัด> เชิงพื้นที่ โดยเส้นห่างกันระดับละ <ค่า>
06เอาไปใช้ต่อ
โค้ดทุกชิ้นอ่านไฟล์ contour-map-sample.csv ชุดเดียวกับที่ Playground ใช้ และตัวเลขในโค้ดเปลี่ยนตามค่าที่คุณปรับด้านล่าง
# ติดตั้ง: pip install "matplotlib==3.10.*" "pandas==2.*"
# ดาวน์โหลด contour-map-sample.csv จากหน้านี้ แล้ววางไว้ข้างสคริปต์
import matplotlib
matplotlib.use("Agg") # รันแบบไม่มีหน้าจอ ถ้ารันในเครื่องตัวเองลบบรรทัดนี้ได้
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from scipy.interpolate import griddata
C1, C2, C3 = "#2a78d6", "#eb6834", "#1baf7a" # palette ของคลัง เปลี่ยนเป็นสีองค์กรได้
INK, SURFACE = "#0b0b0b", "#fcfcfb"
df = pd.read_csv("contour-map-sample.csv")
df["lat"] = pd.to_numeric(df["lat"], errors="coerce")
df["lon"] = pd.to_numeric(df["lon"], errors="coerce")
df["value"] = pd.to_numeric(df["value"], errors="coerce")
LEVELS = "6" # ← ค่าจาก Playground
fig, ax = plt.subplots(figsize=(7.6, 4.2), facecolor=SURFACE)
ax.set_facecolor(SURFACE)
gx, gy = np.mgrid[df["lon"].min():df["lon"].max():200j,
df["lat"].min():df["lat"].max():200j]
gz = griddata((df["lon"], df["lat"]), df["value"], (gx, gy), method="cubic")
cf = ax.contourf(gx, gy, gz, levels=8, cmap="Blues", alpha=0.75)
cs = ax.contour(gx, gy, gz, levels=8, colors="#4a463e", linewidths=0.9)
ax.clabel(cs, inline=True, fontsize=8, fmt="%.0f") # ตัวเลขบนเส้น = จุดแข็งของภาพนี้
ax.scatter(df["lon"], df["lat"], s=10, color="#22201c") # จุดวัดจริง
fig.colorbar(cf, ax=ax, label="ค่าที่วัดได้", shrink=0.8)
ax.spines[["top", "right"]].set_visible(False) # ลดเส้นที่ไม่ได้ให้ข้อมูล
fig.tight_layout()
fig.savefig("contour-map.png", dpi=160)
print("เขียน contour-map.png แล้ว ·", len(df), "แถว")07ลองเล่นเพื่อเข้าใจ
ค่าระหว่างจุดวัดเป็นการประมาณ ไม่ใช่ค่าที่วัดได้จริง — บริเวณที่ไม่มีจุดวัดใกล้เคียงเชื่อถือได้น้อยที่สุด
ดูข้อมูลเป็นตาราง (20 แถว)
| ละติจูด | ลองจิจูด | ค่าที่วัดได้ |
|---|---|---|
| 13.801 | 100.133 | 184 |
| 18.221 | 98.548 | 50.0 |
| 7.663 | 99.011 | 80.0 |
| 14.373 | 101.583 | 162 |
| 18.167 | 100.079 | 178 |
| 8.684 | 98.466 | 162 |
| 14.958 | 102.031 | 138 |
| 19.180 | 98.561 | 71.0 |
| 6.854 | 98.738 | 199 |
| 13.264 | 100.423 | 182 |
| 19.617 | 98.267 | 90.0 |
| 7.085 | 98.117 | 141 |
| 12.458 | 99.895 | 84.0 |
| 18.895 | 98.480 | 148 |
| 6.866 | 96.877 | 120 |
| 13.118 | 100.550 | 65.0 |
| 18.923 | 100.168 | 76.0 |
| 7.398 | 98.207 | 150 |
| 13.792 | 100.146 | 126 |
| 18.545 | 98.655 | 134 |
ลองแล้วจะเห็นอะไร
- จำนวนระดับเส้น: เพิ่มระดับแล้วรายละเอียดมากขึ้นแต่ภาพรกขึ้น — เลือกให้พอดีกับความละเอียดของจุดวัดจริง
ข้อควรระวัง
- ★ ใช้กับข้อมูลที่ไม่ต่อเนื่องในพื้นที่ เช่น รายได้รายเขต ซึ่งไม่มีค่าอยู่ทุกจุด
- ลากเส้นในบริเวณที่ไม่มีจุดวัดเลย ทำให้การเดาดูน่าเชื่อถือเกินจริง
- ไม่ติดตัวเลขบนเส้น ซึ่งทิ้งจุดแข็งที่สุดของรูปแบบนี้ไป
- ใช้ระดับที่ห่างไม่เท่ากันโดยไม่ระบุ ทำให้ระยะห่างระหว่างเส้นอ่านความชันไม่ได้
เมื่อไหร่ไม่ควรใช้กราฟนี้
- ข้อมูลผูกกับเขตการปกครอง→ใช้แทน: choropleth-map
- ข้อมูลเป็นเหตุการณ์แยกกัน ไม่ใช่พื้นผิว→ใช้แทน: kernel-heat-map หรือ hexbin-map
- ต้องการภาพที่อ่านเร็วโดยไม่ต้องอ่านตัวเลข→ใช้แทน: kernel-heat-map