簡潔的線條連接兩個數據點,就像啞鈴的兩端,在對比分析中展現出令人驚豔的清晰度。
在平時的數據分析項目中,我經常會遇到比較兩個相關數據集的變化情況。
這時,傳統的做法是使用堆積條形圖或簇狀條形圖,但它們存在一個共同問題:當我們需要精確追蹤每個項目在兩個時間點或兩種條件下的變化時,這些圖表會讓我們的眼睛在條形之間來回跳躍,難以直觀把握變化的幅度和方向。
今天,我要向大家推薦一種更優雅的替代方案--啞鈴圖。
1. 啞鈴圖是什麼?
啞鈴圖(Dumbbell Plot),有時也稱為DNA圖或槓鈴圖,是一種用於比較兩個相關數據點的可視化圖表。
它源於人們對更有效數據比較方式的持續探索。
在傳統的時間序列比較中,我們通常使用兩條折線,但當需要比較的項目較多時,折線圖會變得混亂。啞鈴圖通過將比較焦點放在每個項目的兩個狀態上,解決了多項目對比時的視覺混亂問題。
它的基本結構很簡單:
- 每個觀察單位(如產品、地區、時間段)對應兩個數據點
- 這兩個數據點由一條直線(或線段)連接
- 整個圖形看起來像一排排啞鈴,因而得名
2. 實現原理
啞鈴圖的核心設計理念是最小化認知負荷。
當我們需要比較A和B時,最直接的方式就是把它們放在一起,用一條線連接,然後觀察這條線的長度(差異大小)和方向(哪個更大)。
在matplotlib中創建啞鈴圖,我們主要使用以下元素:
- 散點圖:表示兩個數據點
- 直線段:連接兩個相關點
- 顏色編碼:通常用不同顏色區分前後狀態或不同組別
- 標籤系統:清晰標識每個觀察單位
3. 實戰示例
接下來,我們看看啞鈴圖在實際場景中的顯示效果。
假設我們是一家電商公司的數據分析師,需要比較8個主要產品類別在2022年和2023年的銷售額變化。
(完整的代碼在文章末尾提供下載地址,文中只截取部分代碼)
先創建一些測試數據:
# 示例數據:8個產品類別在2022年和2023年的銷售額(單位:萬元)
categories = [
"電子產品",
"服裝鞋帽",
"家居用品",
"美妝護膚",
"圖書音像",
"運動户外",
"食品飲料",
"母嬰用品",
]
sales_2022 = [85, 92, 78, 65, 45, 60, 88, 72]
sales_2023 = [95, 87, 85, 78, 52, 73, 95, 80]
然後,我們繪製傳統的簇狀條形圖和啞鈴圖來對比一下效果:
# 創建子圖,對比兩種可視化方法
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 8))
# 簇狀條形圖
x = np.arange(len(categories))
bars1 = ax1.bar(x - width/2, sales_2022, width, label='2022年', color='#4C72B0', alpha=0.8)
bars2 = ax1.bar(x + width/2, sales_2023, width, label='2023年', color='#DD8452', alpha=0.8)
# 在每個條形上添加數值標籤
# 省略 ...
# 啞鈴圖
# 設置y軸位置(每個類別的垂直位置)
y_pos = np.arange(len(categories))
# 繪製連接線
for i, (y2022, y2023) in enumerate(zip(sales_2022, sales_2023)):
# 確定線顏色:增長為綠色,下降為紅色
line_color = '#55A868' if y2023 > y2022 else '#C44E52'
ax2.plot([y2022, y2023], [i, i], color=line_color, linewidth=2.5, alpha=0.7, zorder=1)
# 繪製數據點
ax2.scatter(sales_2022, y_pos, s=120, color='#4C72B0', alpha=0.9, label='2022年', zorder=2, edgecolors='white', linewidth=2)
ax2.scatter(sales_2023, y_pos, s=120, color='#DD8452', alpha=0.9, label='2023年', zorder=2, edgecolors='white', linewidth=2)
# 省略 ...
plt.tight_layout()
plt.show()
通過上面的對比,我們可以清晰地看到啞鈴圖的優勢:
- 變化一目瞭然:連接線的長度直觀表示變化幅度,方向表示增長或下降
- 減少視覺跳躍:眼睛不需要在條形間來回移動,而是沿着水平線自然追蹤
- 突出比較重點:專注於每個項目的兩個狀態對比,而非絕對數值
進一步,我們還可以給啞鈴圖排序,按照增長由快到慢給各個品類排序,這樣自然形成從"下降最顯著"到"增長最顯著"的連續譜,模式自動顯現,無需刻意尋找。
比如上面的啞鈴圖中,【服裝鞋帽】這個品類其實銷售額是下降的,混在一堆啞鈴中不容易看出來吧?
# 創建排序後的啞鈴圖
fig, ax = plt.subplots(figsize=(10, 8))
# 按變化幅度排序
sorted_indices = np.argsort(
[sales_2023[i] - sales_2022[i] for i in range(len(categories))]
)
sorted_categories = [categories[i] for i in sorted_indices]
sorted_2022 = [sales_2022[i] for i in sorted_indices]
sorted_2023 = [sales_2023[i] for i in sorted_indices]
# 繪製連接線
# 省略 ...
# 繪製數據點
# 省略 ...
# 添加變化箭頭標註
# 省略 ...
plt.tight_layout()
plt.show()
這樣改造後,由上到下的啞鈴,越來越短(也就是增長越來越慢),最底部的那個是負增長,用了紅色來標註。
4. 總結
數據可視化的核心目標是有效傳達信息。當我們需要強調變化、比較兩個相關狀態時,啞鈴圖提供了一種簡潔而強大的解決方案。
就像選擇合適的工具完成工作一樣,在面對數據比較任務時,我們應該根據具體需求選擇最合適的可視化形式:
- 當需要比較多個項目的兩個狀態時,選擇啞鈴圖
- 當需要展示單個項目的多個組成部分時,選擇堆積條形圖
- 當需要比較多個項目的多個類別時,選擇簇狀條形圖
最好的可視化不是最複雜的,而是能讓觀眾在最短時間內理解最多信息的那個。
啞鈴圖正是這樣一種高效的工具,它用最簡單的線條連接,講述了數據世界中最動人的變化故事。
下次做報告時,不妨試着把那張擁擠的簇狀條形圖換成啞鈴圖,相信你的觀眾會感嘆:“哇,這張圖做得真專業!”
完整代碼:啞鈴圖.ipynb (訪問密碼: 6872)