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

กราฟพื้นที่ซ้อนตามสัดส่วนNested Proportional Area

ซ้อนรูปเพื่อเทียบขนาดที่ต่างกันหลายเท่า

3
ผสานหลายแนวคิดควรรู้ก่อน · เข้าใจว่าพื้นที่แทนปริมาณและรัศมีต้องใช้รากที่สอง
ลองเล่น

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

Nested proportional area ซ้อนรูปทรงที่พื้นที่แปรตามค่าไว้ที่ฐานเดียวกัน ทำให้เทียบขนาดที่ต่างกันหลายเท่าได้ในพื้นที่จำกัด แต่เพราะพื้นที่อ่านได้หยาบและวงเล็กถูกวงใหญ่บังบางส่วน จึงเหมาะกับการสื่อสารเชิงความรู้สึกมากกว่าการวิเคราะห์

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

เหมือนวางเหรียญหลายขนาดซ้อนกันเพื่อเทียบว่าเหรียญไหนใหญ่กว่ากันเท่าไร

ใช้ที่ไหนบ้าง — อินโฟกราฟิกที่เทียบขนาดที่ต่างกันมาก เช่น งบประมาณของประเทศเทียบกับของเมือง หรือเปรียบเทียบขนาดที่คนนึกภาพไม่ออก

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

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

ตัวอย่างคลาสสิก · ภาพเทียบขนาดในอินโฟกราฟิกสาธารณะ

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

Wikipedia · Proportional area chart

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

เมื่อค่าต่างกันหลายเท่า เช่น 500 กับ 5 กราฟแท่งจะมีแท่งหนึ่งยาวและอีกแท่งเป็นขีดบาง ๆ ซึ่งอ่านยากและเสียพื้นที่

การซ้อนวงกลมที่พื้นที่แปรตามค่าช่วยได้ เพราะพื้นที่โตช้ากว่าความยาว ค่าที่ต่างกัน 100 เท่าจะได้วงที่รัศมีต่างกัน 10 เท่า ซึ่งยังใส่ในภาพเดียวได้

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

การวางให้ฐานล่างตรงกันช่วยการเทียบมาก เพราะได้จุดอ้างอิงร่วมหนึ่งจุด ทำให้เทียบความสูงได้ด้วย ไม่ใช่เทียบพื้นที่อย่างเดียว

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

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

รูปทรงของข้อมูลตารางแบบยาว (หนึ่งแถวหนึ่งสังเกต)
จำนวนมิติที่เข้ารหัสได้2 มิติ
จำนวนแถวที่เหมาะ2–5 รายการขั้นต่ำ 2 แถว
เส้นฐานศูนย์ต้องเริ่มที่ศูนย์พื้นที่แทนปริมาณ ซึ่งวัดจากศูนย์

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

คอลัมน์ทำหน้าที่ชนิดเข้ารหัสด้วยจำนวนค่าที่เหมาะหมายเหตุ
categoryรายการหมวดหมู่text2–6 รายการเกิน 6 วงจะซ้อนกันจนแยกไม่ออก
valueขนาดตัวเลขต่อเนื่องareaบวกเท่านั้น★ รัศมีต้องแปรตามรากที่สองของค่า

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

  1. เรียงจากใหญ่ไปเล็ก
  2. คำนวณรัศมีจากรากที่สอง
  3. ตรวจว่าอัตราส่วนใหญ่สุดต่อเล็กสุดไม่เกินประมาณ 100 เท่า

ค่าที่หายไป — รายการที่ไม่มีค่าต้องแสดงเป็นป้ายพร้อมข้อความ ไม่ใช่วงขนาดศูนย์ที่มองไม่เห็น

สเกลของแกน — พื้นที่แปรตรงกับค่า ซึ่งแปลว่ารัศมีแปรตามรากที่สอง ห้ามใช้สเกลอื่น

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

เกิน 6 วง หรือเมื่อค่าใกล้เคียงกันจนวงซ้อนทับกันเกือบสนิท

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

category,value
กรุงเทพฯ,298
เชียงใหม่,251

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

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

  • อัตราส่วนคร่าว ๆ ระหว่างรายการที่ต่างกันหลายเท่า
  • รายการที่ใหญ่ที่สุด
  • ความรู้สึกถึงขนาดที่ตัวเลขอย่างเดียวสื่อไม่ได้

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

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

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

  1. ดูฐานล่างที่ตรงกันเป็นจุดอ้างอิง
  2. เทียบความสูงของแต่ละวง
  3. อ่านค่าจริงจากป้ายกำกับ

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

  • ใหญ่กว่ากันประมาณกี่เท่า
  • ขนาดนี้ใหญ่แค่ไหนเมื่อเทียบกับสิ่งที่คุ้นเคย

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

  • ใช้รัศมีแปรตรงกับค่า ทำให้ขนาดโกหกหลายเท่า
  • ไม่เขียนค่าจริงกำกับ
  • วงซ้อนกันจนวงเล็กมองไม่เห็น

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

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

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

  1. เขียนค่าจริงกำกับทุกวง
  2. ลากเส้นจากขอบบนของวงไปยังป้ายเพื่อไม่ให้ป้ายทับวง
  3. เทียบกับสิ่งที่คุ้นเคยถ้าทำได้

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

<รายการ> ใหญ่กว่า <รายการ> ประมาณ <เท่า> เท่า

06เอาไปใช้ต่อ

โค้ดทุกชิ้นอ่านไฟล์ nested-area-sample.csv ชุดเดียวกับที่ Playground ใช้ และตัวเลขในโค้ดเปลี่ยนตามค่าที่คุณปรับด้านล่าง

# ติดตั้ง: pip install "matplotlib==3.10.*" "pandas==2.*"
# ดาวน์โหลด nested-area-sample.csv จากหน้านี้ แล้ววางไว้ข้างสคริปต์
import matplotlib
matplotlib.use("Agg")   # รันแบบไม่มีหน้าจอ ถ้ารันในเครื่องตัวเองลบบรรทัดนี้ได้
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

C1, C2, C3 = "#2a78d6", "#eb6834", "#1baf7a"   # palette ของคลัง เปลี่ยนเป็นสีองค์กรได้
INK, SURFACE = "#0b0b0b", "#fcfcfb"

df = pd.read_csv("nested-area-sample.csv")
df["value"] = pd.to_numeric(df["value"], errors="coerce")
SLICES = 5   # ← ค่าจาก Playground

fig, ax = plt.subplots(figsize=(7.6, 4.2), facecolor=SURFACE)
ax.set_facecolor(SURFACE)

d = df.sort_values("value", ascending=False).head(SLICES)
max_v = d["value"].max()
for i, r in enumerate(d.itertuples()):
    rad = np.sqrt(r.value / max_v) * 0.5           # ★ sqrt เพราะสายตาอ่านพื้นที่
    circle = plt.Circle((0.35, rad), rad, fill=False, edgecolor=[C1, C2, C3, "#eda100", "#e87ba4"][i % 5],
                        linewidth=2.4)
    ax.add_patch(circle)
    ax.plot([0.35, 0.72], [rad * 2, rad * 2], color="#c9c6bd", linestyle="--", linewidth=1)
    ax.text(0.74, rad * 2, f"{r.category} · {r.value:,.0f}", va="center", fontsize=9)
ax.set_xlim(-0.2, 1.1); ax.set_ylim(0, 1.1); ax.set_aspect("equal"); ax.axis("off")

ax.spines[["top", "right"]].set_visible(False)   # ลดเส้นที่ไม่ได้ให้ข้อมูล
fig.tight_layout()
fig.savefig("nested-area.png", dpi=160)
print("เขียน nested-area.png แล้ว ·", len(df), "แถว")

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

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

ข้อมูลตัวอย่าง · 6 แถว · seed 42● คำนวณใหม่ในเบราว์เซอร์ทันทีที่ปรับค่า
จำนวนรายการที่แสดง
กรุงเทพฯ · 298กรุงเทพฯ · 298ชลบุรี · 260ชลบุรี · 260ขอนแก่น · 253ขอนแก่น · 253เชียงใหม่ · 251เชียงใหม่ · 251ภูเก็ต · 215ภูเก็ต · 215

รัศมีคำนวณจากรากที่สองของค่าเสมอ ถ้าใช้ค่าตรง ๆ วงจะดูใหญ่เกินจริงหลายเท่า

ใหญ่ที่สุดกรุงเทพฯ
อัตราส่วนใหญ่สุด:เล็กสุด1.4×
จำนวนวง5
ดูข้อมูลเป็นตาราง (5 แถว)
nested area 5 วง
หมวดค่าสัดส่วน
กรุงเทพฯ29821.0%
ชลบุรี26018.3%
ขอนแก่น25317.9%
เชียงใหม่25117.7%
ภูเก็ต21515.2%

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

  • จำนวนวง: เพิ่มจำนวนวงแล้วลองบอกว่าวงที่ 3 กับที่ 4 ต่างกันกี่เท่า จะเห็นว่าทำไม่ได้เลยถ้าไม่อ่านตัวเลข — นี่คือเหตุผลที่ต้องเขียนค่ากำกับเสมอ

ข้อควรระวัง

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

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

  • ค่าใกล้เคียงกันใช้แทน: bar-chart หรือ dot-plot
  • ต้องการอ่านค่าให้แม่นใช้แทน: bar-chart
  • มีมากกว่า 6 รายการใช้แทน: horizontal-bar บนสเกล log

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

เทคนิคถัดไป · กราฟอันดับตามเวลา