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

กราฟพื้นที่ซ้อนStacked Area Chart

ยอดรวมตามเวลา พร้อมบอกว่าใครประกอบอยู่

3
ผสานหลายแนวคิดควรรู้ก่อน · อ่านกราฟพื้นที่และกราฟแท่งซ้อนเป็น
ลองเล่น

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

Stacked area chart คือ stacked bar ที่แกนนอนเป็นเวลาต่อเนื่อง ขอบบนสุดบอกยอดรวมและแต่ละชั้นบอกส่วนประกอบ ข้อจำกัดเหมือนกันคือมีเพียงชั้นล่างสุดที่วางบนเส้นฐานเรียบ ชั้นบน ๆ ต้องขึ้นลงตามชั้นล่างจนอ่านรูปร่างของตัวเองยาก

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

เหมือนดูภาพตัดขวางของชั้นหินที่ทับถมตามเวลา ชั้นล่างสุดวางบนพื้นเรียบจึงอ่านความหนาได้ง่าย ส่วนชั้นบนต้องขึ้นลงตามพื้นผิวของชั้นล่าง

ใช้ที่ไหนบ้าง — ยอดขายรวมรายเดือนแยกตามสินค้า จำนวนผู้ใช้รวมแยกตามแพลตฟอร์ม หรือการใช้พลังงานรวมแยกตามแหล่ง

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

  1. ขั้นที่ 1ตรวจว่าค่าบวกกันได้จริง
  2. ขั้นที่ 2กำหนดลำดับการซ้อนให้คงที่
  3. ขั้นที่ 3วางอนุกรมที่นิ่งที่สุดไว้ชั้นล่าง
  4. ขั้นที่ 4ใส่ legend เรียงตามลำดับการซ้อน

ตัวอย่างคลาสสิก · องค์ประกอบการผลิตไฟฟ้าตามแหล่งพลังงานในรอบยี่สิบปี

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

Our World in Data · Electricity mix

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

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

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

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

ข้อบังคับที่เหมือนกับพื้นที่ปกติคือค่าต้องบวกกันได้จริง ถ้าเป็นอัตราส่วนหรือเปอร์เซ็นต์ของคนละฐาน การซ้อนจะไม่มีความหมายทางคณิตศาสตร์เลย

ถ้าคำถามคือสัดส่วนไม่ใช่ยอดรวม ให้เปลี่ยนไปใช้แบบ 100% ซ้อน ซึ่งขอบบนจะแบนเรียบและอ่านสัดส่วนได้ตรง

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

รูปทรงของข้อมูลตารางแบบยาว (หนึ่งแถวหนึ่งสังเกต)
จำนวนมิติที่เข้ารหัสได้3 มิติ
จำนวนแถวที่เหมาะ3–4 ชั้น × 20–80 จุดเวลาขั้นต่ำ 10 แถว
เส้นฐานศูนย์ต้องเริ่มที่ศูนย์ความหนาของชั้นคือค่า และขอบบนสุดคือยอดรวม ทั้งสองต้องวัดจากศูนย์

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

คอลัมน์ทำหน้าที่ชนิดเข้ารหัสด้วยจำนวนค่าที่เหมาะหมายเหตุ
dateเวลาเวลาx10–150 จุดทุกอนุกรมต้องมีจุดเวลาตรงกัน
seriesอนุกรมที่ซ้อนหมวดหมู่color2–5 ชั้นเกิน 5 ชั้นจะบางจนอ่านไม่ออก
valueปริมาณตัวเลขต่อเนื่องyบวกเท่านั้นต้องเป็นค่าที่บวกกันได้จริง ไม่ใช่อัตราส่วนคนละฐาน

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

  1. ตรวจว่าทุกอนุกรมมีจุดเวลาครบตรงกัน
  2. กำหนดลำดับการซ้อนโดยวางอนุกรมที่นิ่งไว้ล่างสุด
  3. รวมอนุกรมเล็กเป็น "อื่น ๆ"

ค่าที่หายไป — ถ้าอนุกรมใดขาดข้อมูลในช่วงหนึ่ง ยอดรวมจะต่ำกว่าความจริงโดยที่ภาพยังดูปกติ ต้องทำเครื่องหมายช่วงนั้นให้ชัด

สเกลของแกน — linear เริ่มที่ศูนย์ เพราะการซ้อนอาศัยสมบัติการบวก

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

เกิน 6 ชั้น ชั้นบางจะหายไป และถ้าชั้นล่างผันผวนแรงชั้นบนจะอ่านไม่ได้เลย

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

date,series,value

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

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

  • ยอดรวมเปลี่ยนไปอย่างไรตามเวลา จากขอบบนสุด
  • ชั้นล่างสุดเปลี่ยนอย่างไร ซึ่งเป็นชั้นเดียวที่อ่านรูปร่างได้ตรง
  • ชั้นไหนหนาขึ้นหรือบางลงตามเวลา

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

  • ★ อ่านรูปร่างของชั้นที่ไม่ใช่ชั้นล่างสุดได้ยากมาก เพราะมันลอยตามชั้นล่าง
  • ไม่บอกสัดส่วนโดยตรง ต้องใช้แบบ 100% ซ้อน

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

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

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

  • ยอดรวมโตขึ้นไหม
  • การเติบโตมาจากอนุกรมไหน
  • มีอนุกรมไหนที่หดตัวลง

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

  • ชั้นล่างผันผวนแรงจนชั้นบนดูเหมือนผันผวนตาม
  • ชั้นบางจำนวนมากที่มองไม่เห็น
  • ซ้อนค่าที่บวกกันไม่ได้

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

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

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

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

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

ยอดรวมโตจาก <ค่า> เป็น <ค่า> โดยการเติบโตมาจาก <อนุกรม> เป็นหลัก

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

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

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

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

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

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

df["date"] = pd.to_datetime(df["date"])
pivot = df.pivot_table(index="date", columns="series", values="value", aggfunc="sum").fillna(0)
ax.stackplot(pivot.index, *[pivot[c] for c in pivot.columns], labels=list(pivot.columns),
             colors=[C1, C2, C3][: len(pivot.columns)], edgecolor=SURFACE, linewidth=1.2)
ax.set_ylim(0, None)      # การซ้อนอาศัยสมบัติการบวก จึงต้องเริ่มที่ศูนย์
ax.legend(frameon=False, ncols=3, loc="upper left")
fig.autofmt_xdate()

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

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

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

ข้อมูลตัวอย่าง · 26 แถว · seed 29● คำนวณใหม่ในเบราว์เซอร์ทันทีที่ปรับค่า
เทียบความยากของการอ่านชั้นล่างกับชั้นกลาง
หน้าร้านเว็บไซต์แอป
0.0050.0100150200250ก.พ. 68เม.ย. 68มิ.ย. 68หน้าร้าน · ล่าสุด 58.3เว็บไซต์ · ล่าสุด 83.5แอป · ล่าสุด 84.4
เส้นที่นำอยู่ล่าสุดแอป
จำนวนอนุกรม3
ยอดรวมล่าสุด226
ดูข้อมูลเป็นตาราง (26 แถว)
พื้นที่ซ้อน 3 อนุกรม 26 จุดเวลา
วันที่หน้าร้านเว็บไซต์แอป
1/1/256870.753.431.7
8/1/256871.356.131.8
15/1/256868.658.631.6
22/1/256869.357.835.5
29/1/256864.760.941.4
5/2/256864.965.040.1
12/2/256862.267.240.9
19/2/256864.467.544.3
26/2/256863.065.448.8
5/3/256862.465.752.9
12/3/256862.368.551.8
19/3/256863.372.251.1
26/3/256863.372.450.1
2/4/256860.270.852.2
9/4/256856.173.056.5
16/4/256859.677.261.7
23/4/256860.178.066.8
30/4/256858.780.267.6
7/5/256859.681.770.1
14/5/256861.880.973.8
21/5/256860.878.473.7
28/5/256860.180.175.3
4/6/256857.982.677.7
11/6/256856.083.778.3
18/6/256857.086.879.8
25/6/256858.383.584.4

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

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

ข้อควรระวัง

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

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

  • ต้องอ่านรูปร่างของแต่ละอนุกรมให้ตรงใช้แทน: small-multiples หรือ multi-line-chart
  • สนใจสัดส่วนมากกว่ายอดรวมใช้แทน: percent-stacked-bar หรือ streamgraph
  • ค่าบวกกันไม่ได้ใช้แทน: multi-line-chart

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

เทคนิคถัดไป · กราฟกระแสน้ำ