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

แผนที่เส้นชั้นความสูงContour Map

อ่านค่าที่ตำแหน่งใดก็ได้บนพื้นผิวต่อเนื่อง

3
ผสานหลายแนวคิดควรรู้ก่อน · เข้าใจว่าพื้นผิวต่อเนื่องต่างจากข้อมูลรายเขต
ลองเล่น

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

Contour map ลากเส้นเชื่อมจุดที่มีค่าเท่ากัน ทำให้อ่านค่าได้จากตัวเลขบนเส้นและอ่านความชันได้จากระยะห่างระหว่างเส้น ซึ่งเป็นสิ่งที่ heat map ทำไม่ได้ แลกกับการที่ต้องใช้กับปรากฏการณ์ที่ต่อเนื่องจริงเท่านั้น

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

เหมือนแผนที่ภูมิประเทศสำหรับเดินป่าที่เส้นชิดกันแปลว่าชัน และเส้นห่างกันแปลว่าที่ราบ

ใช้ที่ไหนบ้าง — ความสูงของภูมิประเทศ ความกดอากาศ ปริมาณน้ำฝน ระดับเสียงรบกวน หรือความเข้มข้นของมลพิษ

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

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

ตัวอย่างคลาสสิก · แผนที่เส้นชั้นความสูงในการทำแผนที่ภูมิประเทศ

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

Wikipedia · Contour line

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

ปรากฏการณ์บางอย่างต่อเนื่องในพื้นที่จริง ๆ เช่น ความสูงของพื้นดินหรือความกดอากาศ ซึ่งมีค่าอยู่ทุกจุดไม่ว่าเราจะวัดหรือไม่

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

Contour map ลากเส้นเชื่อมจุดที่มีค่าเท่ากันแทน ซึ่งให้สองอย่างที่สีให้ไม่ได้ คือค่าที่อ่านได้ตรง ๆ จากตัวเลขบนเส้น และความชันที่อ่านได้จากระยะห่างระหว่างเส้น

เส้นที่ชิดกันแปลว่าค่าเปลี่ยนเร็วในระยะสั้น ส่วนเส้นที่ห่างกันแปลว่าค่าเปลี่ยนช้า ซึ่งเป็นข้อมูลที่มีค่ามากและอ่านได้ทันทีโดยไม่ต้องคำนวณ

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

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

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

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

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

คอลัมน์ทำหน้าที่ชนิดเข้ารหัสด้วยจำนวนค่าที่เหมาะหมายเหตุ
latละติจูดเชิงพื้นที่yต่อเนื่องพิกัดของจุดวัด
lonลองจิจูดเชิงพื้นที่xต่อเนื่องควรกระจายทั่วพื้นที่
valueค่าที่วัดได้ตัวเลขต่อเนื่องcolorต่อเนื่อง★ ต้องเป็นปรากฏการณ์ที่ต่อเนื่องในพื้นที่จริง

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

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

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

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

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

จุดวัดกระจุกอยู่มุมเดียว ทำให้เส้นในบริเวณอื่นเป็นการเดาล้วน ๆ

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

lat,lon,value
13.8013,100.1331,184
18.2209,98.5482,50

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

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

  • ค่าที่ตำแหน่งใดก็ได้จากเส้นที่ผ่าน
  • บริเวณที่ค่าเปลี่ยนเร็วซึ่งคือที่เส้นชิดกัน
  • ยอดและแอ่งซึ่งคือวงปิดที่ซ้อนกัน

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

  • ★ ค่าในบริเวณที่ไม่มีจุดวัด ซึ่งเป็นการประมาณที่ดูน่าเชื่อถือเกินจริง
  • รายละเอียดที่ละเอียดกว่าระยะห่างระหว่างจุดวัด

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

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

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

  • ที่ตำแหน่งนี้ค่าเท่าไร
  • ตรงไหนที่ค่าเปลี่ยนเร็วที่สุด
  • ยอดสูงสุดและแอ่งต่ำสุดอยู่ที่ไหน

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

  • ใช้กับข้อมูลที่ไม่ต่อเนื่อง เช่น รายได้รายเขต
  • ลากเส้นในบริเวณที่ไม่มีจุดวัดเลย
  • ระดับของเส้นห่างไม่เท่ากันโดยไม่ระบุ

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

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

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

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

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

<ตัวชี้วัด> เชิงพื้นที่ โดยเส้นห่างกันระดับละ <ค่า>

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), "แถว")

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

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

ข้อมูลตัวอย่าง · 40 แถว · seed 347● คำนวณใหม่ในเบราว์เซอร์ทันทีที่ปรับค่า
ความละเอียดของเส้น
ต่ำสูง

ค่าระหว่างจุดวัดเป็นการประมาณ ไม่ใช่ค่าที่วัดได้จริง — บริเวณที่ไม่มีจุดวัดใกล้เคียงเชื่อถือได้น้อยที่สุด

จำนวนชั้น6
จุดวัดจริง40
ค่าสูงสุดที่ประมาณได้914
ดูข้อมูลเป็นตาราง (20 แถว)
contour map จาก 40 จุดวัด
ละติจูดลองจิจูดค่าที่วัดได้
13.801100.133184
18.22198.54850.0
7.66399.01180.0
14.373101.583162
18.167100.079178
8.68498.466162
14.958102.031138
19.18098.56171.0
6.85498.738199
13.264100.423182
19.61798.26790.0
7.08598.117141
12.45899.89584.0
18.89598.480148
6.86696.877120
13.118100.55065.0
18.923100.16876.0
7.39898.207150
13.792100.146126
18.54598.655134

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

  • จำนวนระดับเส้น: เพิ่มระดับแล้วรายละเอียดมากขึ้นแต่ภาพรกขึ้น — เลือกให้พอดีกับความละเอียดของจุดวัดจริง

ข้อควรระวัง

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

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

  • ข้อมูลผูกกับเขตการปกครองใช้แทน: choropleth-map
  • ข้อมูลเป็นเหตุการณ์แยกกัน ไม่ใช่พื้นผิวใช้แทน: kernel-heat-map หรือ hexbin-map
  • ต้องการภาพที่อ่านเร็วโดยไม่ต้องอ่านตัวเลขใช้แทน: kernel-heat-map

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

เทคนิคถัดไป · แผนที่ชุดเปรียบเทียบ