01ภาพรวมของกราฟนี้
Pictogram chart แทนค่าด้วยไอคอนที่ซ้ำกัน หนึ่งไอคอนเท่ากับจำนวนที่กำหนด จุดแข็งคือทำให้ตัวเลขนามธรรมกลายเป็นสิ่งที่นับได้ จึงสื่อสารกับผู้อ่านทั่วไปได้ดีมาก แลกกับความแม่นที่หายไปเพราะต้องปัดเป็นไอคอนเต็มตัว
เปรียบเทียบให้เห็นภาพ
เหมือนบอกว่า "เท่ากับสนามฟุตบอล 12 สนาม" แทนที่จะบอกเป็นตารางเมตร คนฟังนึกภาพออกทันทีแม้ตัวเลขจริงจะปัดไปบ้าง
ใช้ที่ไหนบ้าง — อินโฟกราฟิกสาธารณะ รายงานที่ผู้อ่านไม่คุ้นกับกราฟ หรือการสื่อสารตัวเลขที่ใหญ่จนนึกภาพไม่ออก
สร้างอย่างไร
- ขั้นที่ 1เลือกหน่วยต่อไอคอนที่ทำให้จำนวนไอคอนอยู่ระหว่าง 5 ถึง 30
- ขั้นที่ 2เลือกไอคอนที่สื่อความหมายของหน่วย
- ขั้นที่ 3เรียงไอคอนเป็นแถวที่นับง่าย
- ขั้นที่ 4เขียนกำกับว่าหนึ่งไอคอนเท่ากับเท่าไร
ตัวอย่างคลาสสิก · ระบบ ISOTYPE ของ Otto Neurath ในทศวรรษ 1920
Neurath ออกแบบระบบภาพสัญลักษณ์เพื่อสื่อสารสถิติสังคมให้คนทั่วไปที่อ่านหนังสือไม่คล่องเข้าใจได้ กฎข้อสำคัญที่เขาวางไว้และยังใช้จนถึงวันนี้คือ "จำนวนที่มากกว่าให้ใช้สัญลักษณ์มากกว่า ไม่ใช่สัญลักษณ์ที่ใหญ่กว่า"
02อธิบายภาษาคนเข้าใจง่าย ๆ
ตัวเลขใหญ่ ๆ อย่าง 2,400,000 คน เป็นสิ่งที่คนส่วนใหญ่นึกภาพไม่ออก การเปลี่ยนเป็นไอคอนคน 24 ตัวที่แต่ละตัวแทน 100,000 คน ทำให้สมองจับต้องได้ทันที
เหตุผลที่ได้ผลคือมนุษย์นับของเป็นชิ้น ๆ ได้เก่งกว่าการประเมินความยาวของแท่ง โดยเฉพาะเมื่อไม่คุ้นกับการอ่านกราฟมาก่อน
ราคาที่จ่ายคือความแม่น เพราะต้องปัดเป็นไอคอนเต็มตัว ค่า 2,450,000 กับ 2,350,000 อาจได้ไอคอนเท่ากันทั้งคู่ ดังนั้นต้องเขียนตัวเลขจริงกำกับเสมอ
กติกาที่สำคัญคือไอคอนทุกตัวต้องขนาดเท่ากัน ห้ามขยายไอคอนให้ใหญ่ขึ้นตามค่า เพราะการขยายทั้งกว้างและสูงทำให้พื้นที่โตเป็นกำลังสอง ค่าที่มากกว่าสองเท่าจะดูใหญ่กว่าสี่เท่า
จำนวนไอคอนควรอยู่ในช่วงที่นับไหว ถ้าต้องวาด 200 ไอคอนก็ไม่มีใครนับ ให้เพิ่มค่าต่อไอคอนแทน ภาพจำคือ ถ้านับด้วยตาไม่ไหว ก็เสียจุดแข็งของกราฟนี้ไปแล้ว
03ข้อมูลที่ต้องใช้
คอลัมน์ที่ต้องเตรียม
| คอลัมน์ | ทำหน้าที่ | ชนิด | เข้ารหัสด้วย | จำนวนค่าที่เหมาะ | หมายเหตุ |
|---|---|---|---|---|---|
category | หมวด | หมวดหมู่ | y | 2–6 หมวด | เกิน 6 หมวดภาพจะยาวเกินไป |
value | จำนวน | จำนวนนับ | length | จำนวนนับ | ควรเป็นสิ่งที่นับเป็นหน่วยได้จริง เช่น คน ครัวเรือน ไม่ใช่อัตราส่วน |
ต้องเตรียมข้อมูลอย่างไรก่อนวาด
- เลือกค่าต่อไอคอนให้จำนวนไอคอนอยู่ใน 5–30 ตัว
- บันทึกค่าจริงไว้เขียนกำกับ
- คำนวณว่าการปัดทำให้คลาดไปเท่าไร
ค่าที่หายไป — หมวดที่ไม่มีข้อมูลให้แสดงแถวว่างพร้อมข้อความ ไม่ใช่ไม่มีไอคอนเลย เพราะจะดูเหมือนค่าเป็นศูนย์
สเกลของแกน — เป็นการนับ ไม่มีสเกลต่อเนื่อง ค่าต่อไอคอนคือสิ่งเดียวที่ต้องเลือก
กราฟจะเริ่มพังเมื่อไร
ถ้าหมวดหนึ่งต้องใช้ไอคอนเกิน 30 ตัว ให้เพิ่มค่าต่อไอคอน
หน้าตาไฟล์ที่ต้องเตรียม
category,value
…04อ่านแล้วเห็นอะไร
สิ่งที่เห็นได้จากภาพ
- หมวดไหนมีจำนวนมากที่สุดโดยนับไอคอน
- อัตราส่วนคร่าว ๆ ระหว่างหมวด
- ขนาดของตัวเลขในหน่วยที่จับต้องได้
สิ่งที่กราฟนี้ตอบไม่ได้
- ไม่บอกค่าที่แม่นยำ เพราะทุกค่าถูกปัดเป็นไอคอนเต็มตัว
- ไม่เหมาะกับการเทียบความต่างเล็ก ๆ ที่เล็กกว่าหนึ่งไอคอน
อ่านตามลำดับนี้
- อ่านคำกำกับว่าหนึ่งไอคอนเท่ากับเท่าไรก่อน
- นับไอคอนของแต่ละแถว
- เทียบจำนวนไอคอนระหว่างแถว
คำถามที่ตอบได้
- หมวดนี้มากกว่าหมวดนั้นกี่เท่าโดยประมาณ
- ตัวเลขนี้ใหญ่แค่ไหนในเชิงที่นึกภาพออก
สัญญาณว่ามีอะไรผิด
- ไอคอนขนาดไม่เท่ากัน ซึ่งทำให้พื้นที่โกหก
- ไม่บอกว่าหนึ่งไอคอนเท่ากับเท่าไร
05เหมาะกับการนำเสนอแบบไหน
ทำอย่างไรให้คนอ่านได้ข้อสรุปโดยไม่ต้องบรรยาย
- เขียนค่าจริงเป็นตัวเลขไว้ท้ายแถวทุกแถว
- เขียนคำกำกับค่าต่อไอคอนให้เด่น
- ใช้ไอคอนที่สื่อความหมายของหน่วยจริง
รูปแบบชื่อกราฟที่ควรใช้
<หมวด> มี <ค่า> ซึ่งมากกว่า <หมวด> ประมาณ <เท่า> เท่า
06เอาไปใช้ต่อ
โค้ดทุกชิ้นอ่านไฟล์ pictogram-chart-sample.csv ชุดเดียวกับที่ Playground ใช้ และตัวเลขในโค้ดเปลี่ยนตามค่าที่คุณปรับด้านล่าง
# ติดตั้ง: pip install "matplotlib==3.10.*" "pandas==2.*"
# ดาวน์โหลด pictogram-chart-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("pictogram-chart-sample.csv")
df["value"] = pd.to_numeric(df["value"], errors="coerce")
PER = 50 # ← ค่าจาก Playground
fig, ax = plt.subplots(figsize=(7.6, 4.2), facecolor=SURFACE)
ax.set_facecolor(SURFACE)
d = df.sort_values("value", ascending=False).head(5).reset_index(drop=True)
for i, r in d.iterrows():
n = round(r["value"] / PER)
ax.scatter(range(n), [len(d) - i] * n, s=170, color=C1, marker="o") # ไอคอนขนาดเท่ากันทุกตัว
ax.text(-0.8, len(d) - i, r["category"], ha="right", va="center", fontsize=10)
ax.text(n + 0.4, len(d) - i, f"{r['value']:,.0f}", va="center", fontsize=9, color=INK)
ax.set_xlim(-6, 26); ax.set_ylim(0, len(d) + 1); ax.axis("off")
ax.set_title(f"หนึ่งวงกลม = {PER:,} หน่วย", loc="left")
ax.spines[["top", "right"]].set_visible(False) # ลดเส้นที่ไม่ได้ให้ข้อมูล
fig.tight_layout()
fig.savefig("pictogram-chart.png", dpi=160)
print("เขียน pictogram-chart.png แล้ว ·", len(df), "แถว")07ลองเล่นเพื่อเข้าใจ
การปัดเป็นจำนวนไอคอนเต็มตัวทำให้ค่าที่แสดงคลาดจากค่าจริงเสมอ — เขียนค่าจริงกำกับด้วย
ดูข้อมูลเป็นตาราง (6 แถว)
| หมวด | ค่า | จำนวนไอคอน |
|---|---|---|
| กรุงเทพฯ | 298 | 6 |
| ชลบุรี | 260 | 5 |
| ขอนแก่น | 253 | 5 |
| เชียงใหม่ | 251 | 5 |
| ภูเก็ต | 215 | 4 |
| นครราชสีมา | 140 | 3 |
ลองแล้วจะเห็นอะไร
- หนึ่งไอคอนเท่ากับ: ลดค่าต่อไอคอนจนไอคอนเยอะเกินนับ แล้วเพิ่มจนเหลือไม่กี่ตัว จะเห็นว่ามีช่วงที่พอดีอยู่ประมาณ 5–20 ไอคอนต่อแถว
ข้อควรระวัง
- ขยายขนาดไอคอนตามค่าแทนที่จะเพิ่มจำนวน ทำให้พื้นที่โตเป็นกำลังสองและโกหก
- ใช้ไอคอนมากเกินกว่าจะนับด้วยตา ซึ่งทำให้เสียจุดแข็งของกราฟ
- ไม่เขียนค่าจริงกำกับ ทำให้ผู้อ่านได้แต่ตัวเลขที่ปัดแล้ว
- ใช้ไอคอนครึ่งตัวโดยไม่อธิบายว่าครึ่งตัวหมายถึงอะไร
เมื่อไหร่ไม่ควรใช้กราฟนี้
- ต้องการค่าที่แม่นยำ→ใช้แทน: bar-chart หรือ data-table-viz
- มีหมวดมากกว่า 6 หมวด→ใช้แทน: horizontal-bar
- ค่าเป็นอัตราส่วนหรือดัชนีที่นับเป็นชิ้นไม่ได้→ใช้แทน: bar-chart