01ภาพรวมของกราฟนี้
Cartogram บิดขนาดของแต่ละเขตให้แปรตามค่าแทนที่จะแปรตามพื้นที่จริง แก้ปัญหาหลักของ choropleth ที่เขตพื้นที่ใหญ่แต่คนน้อยครองสายตา แลกกับการที่รูปร่างบิดจนผู้อ่านหาที่คุ้นเคยไม่เจอและต้องใช้เวลาปรับตัว
เปรียบเทียบให้เห็นภาพ
เหมือนแผนที่รถไฟใต้ดินที่บิดระยะทางจริงเพื่อให้อ่านง่าย ซึ่งไม่ตรงกับภูมิศาสตร์แต่ตอบคำถามที่ผู้ใช้ถามจริงได้ดีกว่า
ใช้ที่ไหนบ้าง — ผลการเลือกตั้งที่ต้องให้พื้นที่แทนจำนวนผู้มีสิทธิ์ การกระจายประชากร หรือขนาดเศรษฐกิจรายภูมิภาค
สร้างอย่างไร
- ขั้นที่ 1เลือกค่าที่จะให้พื้นที่แปรตาม
- ขั้นที่ 2เลือกอัลกอริทึมบิดพื้นที่และระบุไว้
- ขั้นที่ 3รักษาความเป็นเพื่อนบ้านของเขตให้มากที่สุด
- ขั้นที่ 4ใส่แผนที่จริงขนาดเล็กไว้ข้างกันเพื่อให้เทียบได้
ตัวอย่างคลาสสิก · Cartogram ผลการเลือกตั้งประธานาธิบดีสหรัฐ
หลังการเลือกตั้งปี 2000 แผนที่รายเคาน์ตีที่แดงเกือบทั้งประเทศทำให้หลายคนเข้าใจผิดเรื่องสัดส่วนคะแนน Mark Newman ตอบด้วย cartogram ที่บิดพื้นที่ตามจำนวนประชากร ซึ่งเปลี่ยนภาพจากประเทศสีแดงเป็นภาพที่สมดุลกว่ามาก และกลายเป็นตัวอย่างที่ถูกอ้างถึงมากที่สุดเรื่องแผนที่ที่ทำให้เข้าใจผิด
02อธิบายภาษาคนเข้าใจง่าย ๆ
ปัญหาที่ choropleth แก้ไม่ได้เลยคือพื้นที่ครองสายตา จังหวัดใหญ่ที่มีคนอยู่น้อยกินพื้นที่บนภาพมากกว่าจังหวัดเล็กที่มีคนเป็นล้าน
ในการเลือกตั้ง ปัญหานี้รุนแรงถึงขั้นเปลี่ยนความเข้าใจ แผนที่ที่แดงเกือบทั้งประเทศอาจมาจากพรรคที่ได้คะแนนน้อยกว่า เพราะพื้นที่ชนบทกว้างแต่คนน้อย
Cartogram แก้ที่รากด้วยการบิดขนาดของเขตให้แปรตามค่าที่เราสนใจ เขตที่มีผู้มีสิทธิ์เลือกตั้งมากก็จะใหญ่ขึ้นตามจำนวนคน ไม่ใช่ตามจำนวนไร่
ผลคือพื้นที่บนภาพสื่อความสำคัญที่แท้จริง ซึ่งแก้การตีความผิดที่ร้ายแรงที่สุดของแผนที่ระบายสีได้ตรงจุด
ราคาที่จ่ายอย่างแรกคือรูปร่างบิด ผู้อ่านที่จำรูปประเทศตัวเองได้จะหาจังหวัดที่คุ้นเคยไม่เจอ และต้องใช้เวลาปรับตัวก่อนจะอ่านได้
อย่างที่สองคืออัลกอริทึมบิดพื้นที่มีหลายแบบ บางแบบรักษารูปร่างไว้มากแต่พื้นที่ไม่ตรงนัก บางแบบพื้นที่ตรงเป๊ะแต่รูปร่างบิดจนจำไม่ได้ ซึ่งเป็นการแลกที่ต้องเลือกอย่างตั้งใจและระบุให้ชัด
03ข้อมูลที่ต้องใช้
คอลัมน์ที่ต้องเตรียม
| คอลัมน์ | ทำหน้าที่ | ชนิด | เข้ารหัสด้วย | จำนวนค่าที่เหมาะ | หมายเหตุ |
|---|---|---|---|---|---|
province | เขตพื้นที่ | เชิงพื้นที่ | shape | 10–80 เขต | ต้องมีไฟล์ขอบเขตประกอบ |
regionไม่บังคับ | ภูมิภาค | หมวดหมู่ | color | 4–8 กลุ่ม | ใช้สีบอกกลุ่มได้ |
rate | ค่าที่กำหนดขนาด | ตัวเลขต่อเนื่อง | area | บวกเท่านั้น | ★ ค่านี้กำหนดพื้นที่ของเขตบนภาพ |
ต้องเตรียมข้อมูลอย่างไรก่อนวาด
- ★ เลือกค่าที่จะให้พื้นที่แปรตามและระบุในชื่อภาพ
- เลือกอัลกอริทึมบิดและบันทึกไว้
- เตรียมแผนที่จริงขนาดเล็กไว้เทียบ
ค่าที่หายไป — เขตที่ไม่มีค่าจะหดจนหายไป ต้องระบุจำนวนเขตที่หายไปเสมอ
สเกลของแกน — พื้นที่แปรตรงกับค่า และสีถ้ามีควรใช้แทนตัวแปรอื่นไม่ใช่ตัวเดียวกับที่กำหนดขนาด
กราฟจะเริ่มพังเมื่อไร
สัดส่วนค่าสูงสุดต่อต่ำสุดเกิน 100 เท่า เขตเล็กจะหายไปหมด
หน้าตาไฟล์ที่ต้องเตรียม
province,region,rate
กรุงเทพฯ,เหนือ,26.6
เชียงใหม่,อีสาน,34.7
…04อ่านแล้วเห็นอะไร
สิ่งที่เห็นได้จากภาพ
- น้ำหนักที่แท้จริงของแต่ละเขตตามค่าที่วัด
- เขตที่ใหญ่ขึ้นหรือหดลงมากเมื่อเทียบกับแผนที่จริง
- การกระจุกตัวของค่าในบางภูมิภาค
สิ่งที่กราฟนี้ตอบไม่ได้
- ★ ตำแหน่งและรูปร่างทางภูมิศาสตร์ที่แท้จริง เพราะถูกบิดโดยตั้งใจ
- ระยะทางระหว่างเขต
- ค่าที่แม่นยำเพราะอ่านจากพื้นที่ซึ่งหยาบ
อ่านตามลำดับนี้
- อ่านก่อนว่าพื้นที่แทนอะไร
- เทียบกับแผนที่จริงข้าง ๆ เพื่อดูว่าเขตไหนโตขึ้นหรือหดลง
- มองหาเขตที่ใหญ่ที่สุดซึ่งคือเขตที่มีน้ำหนักมากที่สุด
คำถามที่ตอบได้
- เขตไหนมีน้ำหนักมากที่สุดจริง ๆ
- ภาพเปลี่ยนไปแค่ไหนเมื่อให้พื้นที่แทนคนแทนที่จะแทนพื้นดิน
- ค่ากระจุกอยู่ที่ไหน
สัญญาณว่ามีอะไรผิด
- ไม่บอกว่าพื้นที่แทนอะไร
- ไม่มีแผนที่จริงไว้เทียบ
- บิดจนเขตที่อยู่ติดกันจริงกลับไม่ติดกันบนภาพ
05เหมาะกับการนำเสนอแบบไหน
ทำอย่างไรให้คนอ่านได้ข้อสรุปโดยไม่ต้องบรรยาย
- ★ วางแผนที่จริงขนาดเล็กไว้ข้าง ๆ เพื่อให้เทียบได้
- เขียนให้ชัดว่าพื้นที่แทนอะไร
- ติดชื่อเขตที่ใหญ่ที่สุดเพื่อเป็นหลักให้ผู้อ่านจับ
รูปแบบชื่อกราฟที่ควรใช้
แผนที่ที่พื้นที่แทน <ตัวแปร> โดย <เขต> ใหญ่ที่สุด
06เอาไปใช้ต่อ
โค้ดทุกชิ้นอ่านไฟล์ cartogram-sample.csv ชุดเดียวกับที่ Playground ใช้ และตัวเลขในโค้ดเปลี่ยนตามค่าที่คุณปรับด้านล่าง
# ติดตั้ง: pip install "matplotlib==3.10.*" "pandas==2.*"
# ดาวน์โหลด cartogram-sample.csv จากหน้านี้ แล้ววางไว้ข้างสคริปต์
import matplotlib
matplotlib.use("Agg") # รันแบบไม่มีหน้าจอ ถ้ารันในเครื่องตัวเองลบบรรทัดนี้ได้
import matplotlib.pyplot as plt
import pandas as pd
import geopandas as gpd
C1, C2, C3 = "#2a78d6", "#eb6834", "#1baf7a" # palette ของคลัง เปลี่ยนเป็นสีองค์กรได้
INK, SURFACE = "#0b0b0b", "#fcfcfb"
df = pd.read_csv("cartogram-sample.csv")
df["rate"] = pd.to_numeric(df["rate"], errors="coerce")
NOTE = "distort" # ← ค่าจาก Playground
fig, ax = plt.subplots(figsize=(7.6, 4.2), facecolor=SURFACE)
ax.set_facecolor(SURFACE)
# pip install cartogrampy หรือใช้ non-contiguous cartogram แบบง่าย
gdf = gpd.read_file("provinces.geojson").merge(df, on="province")
scale = (gdf["rate"] / gdf["rate"].max()) ** 0.5 # รากที่สอง → พื้นที่แปรตามค่า
shrunk = gdf.copy()
shrunk["geometry"] = [
gpd.GeoSeries(g).scale(s, s, origin=g.centroid).iloc[0]
for g, s in zip(gdf.geometry, scale)]
gdf.plot(ax=ax, facecolor="none", edgecolor="#e2e0da", linewidth=0.5) # โครงจริงไว้เทียบ
shrunk.plot(ax=ax, column="region", cmap="tab10", edgecolor="#fcfcfb", linewidth=0.8)
ax.set_axis_off()
ax.spines[["top", "right"]].set_visible(False) # ลดเส้นที่ไม่ได้ให้ข้อมูล
fig.tight_layout()
fig.savefig("cartogram.png", dpi=160)
print("เขียน cartogram.png แล้ว ·", len(df), "แถว")07ลองเล่นเพื่อเข้าใจ
ขนาดช่องแปรตามค่า ไม่ใช่ตามพื้นที่จริง — ผู้อ่านต้องรู้ข้อนี้ก่อน ไม่อย่างนั้นจะอ่านผิด
ดูข้อมูลเป็นตาราง (12 แถว)
| จังหวัด | ภูมิภาค | ค่า (ต่อประชากรหมื่นคน) |
|---|---|---|
| กรุงเทพฯ | เหนือ | 26.6 |
| เชียงใหม่ | อีสาน | 34.7 |
| ขอนแก่น | กลาง | 32.7 |
| ชลบุรี | ตะวันออก | 34.4 |
| ภูเก็ต | ตะวันตก | 26.8 |
| นครราชสีมา | ใต้ | 18.3 |
| สงขลา | เหนือ | 10.4 |
| อุดรธานี | อีสาน | 23.1 |
| สุราษฎร์ธานี | กลาง | 20.1 |
| พิษณุโลก | ตะวันออก | 17.9 |
| ระยอง | ตะวันตก | 17.4 |
| นครปฐม | ใต้ | 10.5 |
ลองแล้วจะเห็นอะไร
- สังเกตอะไร: เทียบกับหน้า choropleth-map ที่ใช้ข้อมูลชุดเดียวกัน จะเห็นว่าเขตที่เคยครองสายตาเพราะพื้นที่ใหญ่หดลงจนเล็ก
ข้อควรระวัง
- ไม่บอกว่าพื้นที่แทนอะไร ทำให้ผู้อ่านคิดว่าแผนที่ผิด
- ไม่วางแผนที่จริงไว้เทียบ ทำให้ผู้อ่านหาที่คุ้นเคยไม่เจอ
- ใช้กับข้อมูลที่ค่าต่างกันมากเกินจนเขตเล็กหายไปหมด
- ใช้สีแทนตัวแปรเดียวกับที่กำหนดขนาด ซึ่งซ้ำซ้อนโดยเปล่าประโยชน์
เมื่อไหร่ไม่ควรใช้กราฟนี้
- ผู้อ่านต้องใช้แผนที่หาตำแหน่งจริง→ใช้แทน: choropleth-map
- ต้องการความเป็นระเบียบและอ่านง่าย→ใช้แทน: tile-grid-map
- ต้องเทียบค่าให้แม่น→ใช้แทน: horizontal-bar