01ภาพรวมของกราฟนี้
Bar chart race แสดงกราฟแท่งที่เรียงอันดับใหม่ทีละช่วงเวลาแบบเคลื่อนไหว จุดแข็งคือดึงความสนใจได้ดีมากในสื่อสังคม จุดอ่อนที่ร้ายแรงคือผู้ชมจำสถานะก่อนหน้าไม่ได้ จึงเปรียบเทียบข้ามเวลาได้แย่กว่ากราฟนิ่งอย่าง bump chart มาก
เปรียบเทียบให้เห็นภาพ
เหมือนดูการแข่งวิ่งถ่ายทอดสด เราตื่นเต้นตามได้ แต่ถ้าถามว่านักวิ่งคนนี้ทำเวลาดีขึ้นกว่ารอบที่แล้วไหม เราตอบไม่ได้เพราะไม่มีภาพเปรียบเทียบ
ใช้ที่ไหนบ้าง — สื่อสังคมและวิดีโอที่ต้องการดึงความสนใจ การนำเสนอที่มีผู้บรรยายอธิบายควบคู่ หรือการเปิดประเด็นก่อนแสดงกราฟนิ่งที่วิเคราะห์ได้
สร้างอย่างไร
- ขั้นที่ 1จัดข้อมูลเป็นค่าของแต่ละรายการในแต่ละช่วงเวลา
- ขั้นที่ 2เรียงอันดับใหม่ในทุกเฟรม
- ขั้นที่ 3ผูกสีกับตัวตนของรายการไม่ใช่กับอันดับ
- ขั้นที่ 4ใส่ปุ่มหยุดและตัวเลื่อนเวลาเสมอ
ตัวอย่างคลาสสิก · กระแสกราฟแท่งแข่งขันบนสื่อสังคมปี 2019
วิดีโอกราฟแท่งแข่งขันที่แสดงอันดับแบรนด์หรือเมืองตามปีได้รับความนิยมอย่างมากบนสื่อสังคม ซึ่งพิสูจน์จุดแข็งของมันเรื่องการดึงความสนใจ แต่ก็ถูกวิจารณ์จากนักออกแบบข้อมูลว่าให้ข้อมูลน้อยกว่า bump chart ที่แสดงทุกอย่างในภาพเดียวและอ่านได้ในไม่กี่วินาที
02อธิบายภาษาคนเข้าใจง่าย ๆ
กราฟแท่งแข่งขันได้รับความนิยมมากในสื่อสังคมเพราะมันเคลื่อนไหว ซึ่งดึงสายตาได้ดีกว่ากราฟนิ่งอย่างเห็นได้ชัด
แต่ในแง่การอ่านข้อมูล มันมีจุดอ่อนที่แก้ไม่ได้ คือผู้ชมเห็นได้ทีละเฟรม และความจำระยะสั้นของคนจำสถานะก่อนหน้าได้ไม่กี่วินาที
ผลคือคำถามอย่าง "รายการนี้ไต่ขึ้นมาตั้งแต่เมื่อไร" หรือ "ใครแซงใครกี่ครั้ง" ตอบไม่ได้เลยจากภาพเคลื่อนไหว ทั้งที่ bump chart ตอบได้ในภาพเดียว
กติกาทางเทคนิคที่ห้ามละเมิดคือสีต้องผูกกับตัวตนของรายการ ไม่ใช่กับอันดับ ถ้าสีเปลี่ยนเมื่อสลับอันดับ ผู้ชมจะตามรายการเดิมไม่ได้เลย
ข้อควรทำเสมอคือมีปุ่มหยุดและตัวเลื่อนเวลา เพื่อให้ผู้ชมหยุดดูเฟรมที่สนใจได้ และควรเคารพการตั้งค่าลดการเคลื่อนไหวของผู้ใช้ที่ไวต่อภาพเคลื่อนไหว
03ข้อมูลที่ต้องใช้
คอลัมน์ที่ต้องเตรียม
| คอลัมน์ | ทำหน้าที่ | ชนิด | เข้ารหัสด้วย | จำนวนค่าที่เหมาะ | หมายเหตุ |
|---|---|---|---|---|---|
brand | รายการที่แข่งกัน | หมวดหมู่ | color | 5–15 รายการ | ★ สีต้องผูกกับตัวตนของรายการ ไม่ใช่กับอันดับ |
period | ช่วงเวลา | มีลำดับ | order | 10–100 เฟรม | ยิ่งเฟรมถี่ภาพยิ่งลื่น |
score | ค่าที่ใช้จัดอันดับ | ตัวเลขต่อเนื่อง | length | ต่อเนื่อง | ความยาวแท่งแปรตามค่านี้ |
ต้องเตรียมข้อมูลอย่างไรก่อนวาด
- จัดให้ทุกรายการมีค่าในทุกช่วงเวลา
- คำนวณอันดับในแต่ละเฟรม
- เพิ่มเฟรมระหว่างกลางด้วยการประมาณค่าเพื่อให้ภาพลื่น และระบุว่าทำแล้ว
ค่าที่หายไป — รายการที่ยังไม่มีข้อมูลในช่วงต้นควรไม่ปรากฏเลย ไม่ใช่แสดงเป็นแท่งศูนย์ เพราะแท่งศูนย์แปลว่ามีอยู่แต่ค่าเป็นศูนย์
สเกลของแกน — แกนค่าอาจปรับตามเฟรมหรือตรึงไว้ ถ้าปรับตามเฟรมต้องระบุ เพราะจะทำให้ความยาวแท่งเทียบข้ามเฟรมไม่ได้
กราฟจะเริ่มพังเมื่อไร
เกิน 15 รายการ ผู้ชมตามไม่ทันเพราะแท่งสลับที่เร็วเกินไป
หน้าตาไฟล์ที่ต้องเตรียม
period,brand,score,rank
ม.ค.,แบรนด์ ก,99.1,1
ม.ค.,แบรนด์ ข,89.9,2
…04อ่านแล้วเห็นอะไร
สิ่งที่เห็นได้จากภาพ
- อันดับ ณ เฟรมที่กำลังดู
- ความรู้สึกถึงการเปลี่ยนแปลงโดยรวม
- ช่วงเวลาที่มีการสลับอันดับกันวุ่นวาย
สิ่งที่กราฟนี้ตอบไม่ได้
- ★ เทียบข้ามเวลาไม่ได้เลย เพราะเห็นได้ทีละเฟรมและความจำระยะสั้นจำไม่ได้
- ไม่บอกว่าใครไต่ขึ้นมาตั้งแต่เมื่อไร
- นับจำนวนครั้งที่แซงกันไม่ได้
อ่านตามลำดับนี้
- หยุดที่เฟรมที่สนใจแล้วอ่านเหมือนกราฟแท่งธรรมดา
- ใช้ตัวเลื่อนเวลาเพื่อเทียบสองเฟรม
- ถ้าต้องการวิเคราะห์จริง ให้ดู bump chart ควบคู่
คำถามที่ตอบได้
- ตอนนี้ใครนำ
- มีการแซงกันเกิดขึ้นไหม
สัญญาณว่ามีอะไรผิด
- สีเปลี่ยนตามอันดับแทนที่จะผูกกับตัวตนของรายการ
- ไม่มีปุ่มหยุดหรือตัวเลื่อนเวลา
- แกนค่าปรับตามเฟรมโดยไม่บอก
05เหมาะกับการนำเสนอแบบไหน
ทำอย่างไรให้คนอ่านได้ข้อสรุปโดยไม่ต้องบรรยาย
- แสดงป้ายช่วงเวลาให้เด่นเสมอ
- ใส่ปุ่มหยุดและตัวเลื่อนเวลา
- เคารพการตั้งค่าลดการเคลื่อนไหวของผู้ใช้
- แสดง bump chart หรือกราฟนิ่งควบคู่สำหรับการวิเคราะห์
รูปแบบชื่อกราฟที่ควรใช้
<รายการ> ขึ้นเป็นอันดับหนึ่งใน <ช่วงเวลา>
06เอาไปใช้ต่อ
โค้ดทุกชิ้นอ่านไฟล์ bar-race-sample.csv ชุดเดียวกับที่ Playground ใช้ และตัวเลขในโค้ดเปลี่ยนตามค่าที่คุณปรับด้านล่าง
# ติดตั้ง: pip install "matplotlib==3.10.*" "pandas==2.*"
# ดาวน์โหลด bar-race-sample.csv จากหน้านี้ แล้ววางไว้ข้างสคริปต์
import matplotlib
matplotlib.use("Agg") # รันแบบไม่มีหน้าจอ ถ้ารันในเครื่องตัวเองลบบรรทัดนี้ได้
import matplotlib.pyplot as plt
import pandas as pd
from matplotlib.animation import FuncAnimation
C1, C2, C3 = "#2a78d6", "#eb6834", "#1baf7a" # palette ของคลัง เปลี่ยนเป็นสีองค์กรได้
INK, SURFACE = "#0b0b0b", "#fcfcfb"
df = pd.read_csv("bar-race-sample.csv")
df["score"] = pd.to_numeric(df["score"], errors="coerce")
df["rank"] = pd.to_numeric(df["rank"], errors="coerce")
FRAME = 7 # ← ค่าจาก Playground
fig, ax = plt.subplots(figsize=(7.6, 4.2), facecolor=SURFACE)
ax.set_facecolor(SURFACE)
periods = list(dict.fromkeys(df["period"]))
brands = list(dict.fromkeys(df["brand"]))
colors = {b: [C1, C2, C3, "#eda100", "#e87ba4"][i % 5] for i, b in enumerate(brands)}
# ★ สีผูกกับตัวตนของแบรนด์ ไม่ใช่กับอันดับ
def draw(k):
ax.clear()
snap = df[df["period"] == periods[k]].sort_values("score")
ax.barh(snap["brand"], snap["score"], color=[colors[b] for b in snap["brand"]], height=0.66)
ax.set_xlim(0, df["score"].max() * 1.05) # ตรึงแกนไว้เพื่อให้เทียบข้ามเฟรมได้
ax.text(0.98, 0.06, periods[k], transform=ax.transAxes, ha="right", fontsize=26, color="#b5b2aa")
anim = FuncAnimation(fig, draw, frames=len(periods), interval=700)
anim.save("bar-race.gif", writer="pillow", dpi=110)
print("เขียน bar-race.gif แล้ว")
raise SystemExit
ax.spines[["top", "right"]].set_visible(False) # ลดเส้นที่ไม่ได้ให้ข้อมูล
fig.tight_layout()
fig.savefig("bar-race.png", dpi=160)
print("เขียน bar-race.png แล้ว ·", len(df), "แถว")07ลองเล่นเพื่อเข้าใจ
ภาพเคลื่อนไหวทำให้จำอันดับก่อนหน้าไม่ได้ ถ้าต้องการเทียบข้ามเวลาจริง ๆ ใช้ bump chart หรือ small multiples
ดูข้อมูลเป็นตาราง (5 แถว)
| อันดับ | แบรนด์ | คะแนน |
|---|---|---|
| 1 | แบรนด์ ข | 106 |
| 2 | แบรนด์ ก | 104 |
| 3 | แบรนด์ ง | 103 |
| 4 | แบรนด์ ค | 75.0 |
| 5 | แบรนด์ จ | 63.8 |
ลองแล้วจะเห็นอะไร
- ช่วงเวลา: เลื่อนกลับไปกลับมาแล้วลองตอบว่ารายการหนึ่งไต่ขึ้นหรือตกลงตั้งแต่เฟรมแรก จะพบว่าตอบยากมาก — นี่คือจุดอ่อนหลักของภาพเคลื่อนไหว ลองเทียบกับหน้า bump-chart ที่ตอบได้ทันที
ข้อควรระวัง
- ★ ผูกสีกับอันดับแทนที่จะผูกกับตัวตนของรายการ ทำให้ตามรายการเดิมไม่ได้เลย
- ไม่มีปุ่มหยุดหรือตัวเลื่อนเวลา ทำให้ผู้ชมดูรายละเอียดไม่ได้
- ปรับแกนค่าตามแต่ละเฟรมโดยไม่บอก ทำให้ความยาวแท่งเทียบข้ามเฟรมไม่ได้
- ใช้แทนกราฟวิเคราะห์ ทั้งที่ตอบคำถามเชิงเปรียบเทียบข้ามเวลาไม่ได้เลย
- ไม่เคารพการตั้งค่าลดการเคลื่อนไหวของผู้ใช้ที่ไวต่อภาพเคลื่อนไหว
เมื่อไหร่ไม่ควรใช้กราฟนี้
- ต้องการวิเคราะห์การเปลี่ยนอันดับ→ใช้แทน: bump-chart ที่แสดงทุกช่วงเวลาในภาพเดียว
- เป็นเอกสารที่พิมพ์หรืออ่านเงียบ ๆ→ใช้แทน: small-multiples หรือ bump-chart
- มีเพียงสองช่วงเวลา→ใช้แทน: slope-chart หรือ dumbbell-chart