想象一下面積圖就像一層層疊起來的彩色玻璃片,每一層代表一個類別,從下往上堆疊,形成整體的視覺衝擊。
但有時我們需要更特別的方式來展示數據的變化:是像河流一樣蜿蜒流淌,還是像地平線上的羣山連綿起伏?
今天,本文將介紹兩種創意面積圖變體——流圖和地平線圖,它們能讓你的時間序列數據講述更生動的故事。
1. 流圖:數據的河流
如果把傳統的堆疊面積圖想象成一塊塊整齊堆疊的積木,那麼流圖就像一條蜿蜒流淌的河流,河道的寬窄變化自然流暢,波峯波谷過渡平滑。
它特別適合展示多個類別數據隨時間的變化趨勢,尤其是當你想強調整體流動感和各部分的相對比例變化時。
流圖的核心思想是將傳統的堆疊面積圖進行"平滑"處理。
在matplotlib中,我們可以使用fill_between函數結合樣條插值來創建平滑的邊緣。
關鍵在於將堆疊的數據進行累積,然後對累積邊界進行平滑處理。
# 數據準備
x = np.linspace(0, 10, 100)
# 構造三組波浪數據
y1 = 2 + np.sin(x) # 基礎波動
y2 = 2 + np.cos(x - 1.5) # 錯位波動
y3 = 2 + np.sin(x + 2) # 再次錯位
# 省略 ...
# 繪圖設置
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))
# --- 左圖:普通堆疊面積圖 (baseline='zero') ---
ax1.stackplot(x, y_data, labels=labels, colors=colors, baseline='zero', alpha=0.8)
# 省略 ...
# --- 右圖:流圖 (baseline='sym') ---
# 'sym' 表示對稱中心佈局
ax2.stackplot(x, y_data, labels=labels, colors=colors, baseline='sym', alpha=0.8)
ax2.axhline(0, color='black', ls='--', alpha=0.1) # 畫一條中心參考線
# 省略 ...
# 去除右圖邊框,增加流動感
for spine in ax2.spines.values():
spine.set_visible(False)
plt.tight_layout()
plt.show()
流圖解決了一個視覺錯覺問題:在普通堆疊面積圖中,上面的數據層會因為下面數據層的起伏而被迫“扭曲”,很難看出它原本的形狀。
流圖通過中心佈局,減少了這種扭曲,非常適合展示隨時間變化的趨勢和不同類別權重的波動,這種有機的形態還能給讀者帶來極強的審美愉悦感。
2. 地平線圖:數據的羣山
想象一下遠處的地平線上有一排連綿的山脈,每座山的高度代表一個數據值。
地平線圖就是這樣一種可視化技術,它將時間序列數據壓縮在一個很小的垂直空間內,通過顏色和分層來展示數據的變化。
特別適合在有限空間內展示多個時間序列的對比。
地平線圖的核心思想是數據分層和顏色漸變。
它將數據值分成若干層(通常是2-3層),每層用一種顏色表示。當數據值超過一層時,就用更深的顏色或不同的顏色填充。這樣可以在很小的垂直空間內展示很大的數據範圍。
from datetime import timedelta
# 生成模擬數據:過去10年五大科技公司的股價波動
np.random.seed(42)
# 生成日期範圍:過去10年,每月一個數據點
dates = pd.date_range("2013-01-01", "2023-01-01", freq="ME")
companies = ["蘋果", "谷歌", "微軟", "亞馬遜", "Meta"]
# 生成各公司的股價模擬數據(標準化到相似範圍)
data = {}
for company in companies:
# 基礎趨勢:每家公司有不同的增長趨勢,但最終都在70-90範圍內
# 省略 ...
# 轉換為DataFrame
df = pd.DataFrame(data, index=dates)
# 創建對比圖表
fig, axes = plt.subplots(2, 1, figsize=(14, 10))
# ============ 傳統堆疊面積圖 ============
colors = ["#FF6B6B", "#4ECDC4", "#45B7D1", "#FFD166", "#9B5DE5"]
# 為堆疊面積圖重新歸一化數據
df_normalized = df.div(df.sum(axis=1), axis=0) * 100
y_cumulative = np.zeros(len(df))
for i, company in enumerate(companies):
axes[0].fill_between(
df.index,
y_cumulative,
y_cumulative + df_normalized[company].values,
color=colors[i],
alpha=0.7,
label=company,
edgecolor="white",
linewidth=0.5,
)
y_cumulative += df_normalized[company].values
# 省略 ...
# ============ 地平線圖:股價波動對比 ============
# 生成股價變化百分比數據(更能體現波動對比)
np.random.seed(42)
price_changes = {}
for company in companies:
# 生成均值附近波動的變化數據
# 省略 ...
# 關鍵參數:定義“波段”
BAND_HEIGHT = 3.0 # 每個顏色波段代表的變化率幅度 (%)
NUM_BANDS = 3 # 正負方向各使用的波段層數
df = pd.DataFrame(price_changes, index=dates)
# 為每家公司計算並繪製地平線
for i, company in enumerate(companies):
# 公司的基準Y軸位置(水平線)
# 省略 ...
# 分層與繪製:從第1層到第NUM_BANDS層
for band in range(NUM_BANDS):
# --- 處理正偏差(上漲)---
# 計算當前層的數據:偏差值減去已繪製層的高度,並限制在本層高度內
# 省略 ...
# --- 處理負偏差(下跌)---
# 對負值取絕對值,進行類似處理
# 省略 ...
# 美化圖表
# 省略 ...
# 6. 添加圖例
import matplotlib.patches as mpatches
legend_patches = []
# 省略 ...
plt.tight_layout(h_pad=5)
plt.show()
地平線圖是空間利用大師。當你有 20 個股票或者 50 個城市的温度需要放在一張圖裏對比時,普通的面積圖會擠成一團亂麻。
地平線圖可以將每個序列壓縮成一個窄窄的橫條,但在保持視覺分辨率的同時,還能讓你看清極值(通過深顏色)。
3. 總結
數據可視化不僅是科學,也是藝術。流圖和地平線圖這兩種面積圖變體,分別從"流動之美"和"空間效率"兩個角度拓展了面積圖的可能性。
它們證明了,通過對基礎圖表的創意改造,我們可以讓數據講述更豐富、更生動的故事。
下次當你面對時間序列數據時,不妨問問自己:我的數據像一條蜿蜒的河流,還是像地平線上的羣山?選擇適合的可視化方式,讓你的數據真正"流動"起來或"層疊"起來。
記住,最好的可視化不是最複雜的,而是最能清晰傳達信息、啓發思考的那一個。
完整的代碼共享在:面積圖的2個變種.ipynb (訪問密碼: 6872)