博客 / 詳情

返回

棒棒糖圖:當條形圖遇上極簡美學

棒棒糖圖(Lollipop Chart)可以看作是條形圖的一種“輕盈版”變體:它用一根從基準線延伸出來的“棒”,並在末端以一個“糖”(圓點)來表示數值,取代了傳統的矩形條。

這種圖表傳達的信息與條形圖是一樣的,但它更注重突出數據點的位置,整體看起來更加清新、現代。

今天,我們一起探索棒棒糖圖的優勢,並通過代碼實現,親手打造一個屬於自己的棒棒糖圖!

設計原理

設計棒棒糖圖的初衷有兩個方面:

首先,通過減少圖形中的“墨水”使用量,在面對大量類別或數值普遍較高的情況下,避免了條形圖過於密集可能帶來的視覺壓迫感雜亂無章的感覺;

其次,這樣的設計能夠更好地引導觀察者的注意力集中在各個數據點的具體位置及其之間的差異上,非常適合用來進行排名或者對比分析。

棒棒糖圖條形圖在功能上是等價的,也並不總是優於條形圖。

當處理大量類別、條柱非常高且相互之間距離較近的數據時,棒棒糖圖會顯得更加易於閲讀理解;

然而,在需要強調絕對數量或是希望獲得最為直觀長度比較的情況下,條形圖依然是更好的選擇。

實現原理

棒棒糖圖matplotlib庫中沒有直接對應的類。

不過,它的實現原理非常簡單,通過組合使用 matplotlib 中的兩個基本繪圖功能就可以實現:

  1. 繪製線條 (plt.vlines):這是構成棒棒糖“棍子”部分的關鍵。

plt.vlines 函數用於在圖表上繪製垂直線段。通過指定每個數據點的 x 座標、線條的起始點(通常是 0)和結束點(即對應數據的 y 值),就可以畫出從 x 軸延伸到數據值的線條。

  1. 繪製圓點 (plt.scatter):這是構成棒棒糖“糖”部分的關鍵。

plt.scatter 函數用於繪製散點圖。通過將每個數據點的 x 座標和 y 座標(即數據值)作為參數傳入,就可以在每條線的頂端繪製一個圓點。

總的來説,實現原理就是:用線條表示數值的大小,用圓點強調數值的終點位置,兩者結合就形成了視覺上類似棒棒糖的圖表。

這種組合方式使得圖表比實心的條形圖更簡潔,同時又能清晰地傳達數據信息。

下一節的示例中,將會演示如何使用matplotlib來繪製棒棒糖圖

應用示例

接下來,讓我們通過實際的對比示例,直觀地感受棒棒糖圖與傳統條形圖的不同表現。

適合棒棒糖圖的場景

# 創建更多類別的測試數據
# 模擬不同月份中每天的某個指標(例如:每日平均步數,單位:千步)
days = [f"Day {i}" for i in range(1, 21)]  # 生成 20 天的數據
np.random.seed(42)  # 設置隨機種子,確保每次運行結果一致
# 生成 1 到 5 之間的隨機數值作為示例數據
values = np.round(np.random.uniform(1.0, 5.0, size=len(days)), 1)

# --- 創建子圖 ---
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 10))  # 調整為垂直佈局,方便比較

# --- 繪製條形圖 (上圖) ---
bars = ax1.bar(days, values, color="skyblue", edgecolor="navy", linewidth=0.7)
ax1.set_title("條形圖 (Bar Chart) - 每日步數", fontsize=14)
ax1.set_ylabel("數值 (千步)")
# ax1.set_xlabel('日期') # x軸標籤已在下方圖中
ax1.grid(axis="y", linestyle="--", alpha=0.7)
# 在條形圖上添加數值標籤
for bar, val in zip(bars, values):
    height = bar.get_height()
    ax1.text(
        bar.get_x() + bar.get_width() / 2.0,
        height + 0.05,
        f"{val}",
        ha="center",
        va="bottom",
        fontsize=8,
    )  # 標籤旋轉90度節省空間

# --- 繪製棒棒糖圖 (下圖) ---
# 1. 繪製線條
ax2.vlines(x=range(len(days)), ymin=0, ymax=values, color="navy", linewidth=2)
# 2. 在線條頂部繪製圓點
ax2.scatter(x=range(len(days)), y=values, color="red", s=50, zorder=3)
# 3. 添加數值標籤
for i, val in enumerate(values):
    ax2.text(i, val + 0.1, f"{val}", ha="center", va="bottom", fontsize=8)

ax2.set_title("棒棒糖圖 (Lollipop Chart) - 每日步數", fontsize=14)
ax2.set_ylabel("數值 (千步)")
ax2.set_xlabel("日期")
ax2.set_xticks(range(len(days)))
ax2.set_xticklabels(days, rotation=45, ha="right")  # 旋轉x軸標籤以便閲讀
ax2.grid(axis="y", linestyle="--", alpha=0.7)
ax2.set_ylim(0, max(values) * 1.1)

# --- 顯示圖形 ---
plt.tight_layout()  # 調整子圖間距
plt.show()

這個示例使用了20個數據類別(Day 1 到 Day 20)。

你可以看到,在條形圖中,許多藍色的條形緊密地排列在一起,視覺上顯得有些擁擠。

而在棒棒糖圖中,線條和圓點使得數據點之間的關係更加清晰,整體視覺效果更輕盈,更容易比較各個數值的大小和識別模式。

適合傳統條形圖的場景

# 創建更適合條形圖的測試數據
# 模擬某公司連續12個月的銷售額(單位:萬元)
months = [
    "1月",
    "2月",
    "3月",
    "4月",
    "5月",
    "6月",
    "7月",
    "8月",
    "9月",
    "10月",
    "11月",
    "12月",
]
# 生成有一定趨勢和波動的銷售額數據,例如有季節性高峯
sales = [120, 110, 135, 140, 155, 170, 185, 180, 160, 150, 145, 165]

# --- 創建子圖 ---
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 6))

# --- 繪製條形圖 (左圖) ---
bars = ax1.bar(months, sales, color="lightsteelblue", edgecolor="black", linewidth=0.7)
ax1.set_title("條形圖 (Bar Chart - 月份銷售額)", fontsize=14)
ax1.set_ylabel("銷售額 (萬元)")
ax1.set_xlabel("月份")
ax1.grid(axis="y", linestyle="--", alpha=0.7)
# 在條形圖上添加數值標籤
for bar, s in zip(bars, sales):
    height = bar.get_height()
    ax1.text(
        bar.get_x() + bar.get_width() / 2.0,
        height + 2,
        f"{s}",
        ha="center",
        va="bottom",
        fontsize=9,
    )

# --- 繪製棒棒糖圖 (右圖) ---
ax2.vlines(x=range(len(months)), ymin=0, ymax=sales, color="gray", linewidth=2)
ax2.scatter(x=range(len(months)), y=sales, color="coral", s=50, zorder=3)
for i, s in enumerate(sales):
    ax2.text(i, s + 3, f"{s}", ha="center", va="bottom", fontsize=9)

ax2.set_title("棒棒糖圖 (Lollipop Chart - 月份銷售額)", fontsize=14)
ax2.set_ylabel("銷售額 (萬元)")
ax2.set_xlabel("月份")
ax2.set_xticks(range(len(months)))
ax2.set_xticklabels(months, rotation=45)  # 旋轉x軸標籤以防重疊
ax2.grid(axis="y", linestyle="--", alpha=0.7)
ax2.set_ylim(0, max(sales) * 1.1)

# --- 顯示圖形 ---
plt.tight_layout()
plt.show()

在這個示例中,數據代表的是連續的月份,數值本身代表的是銷售額,這是一個“量”的概念。

條形圖的實心塊能讓人立刻感受到哪個月份的銷售額更高,整體的分佈和對比關係一目瞭然。

而棒棒糖圖雖然也展示了數據,但線條和圓點的組合在視覺上不如實心條形那樣能直接傳達“量”的感覺,尤其是在數值差異不是特別巨大時,對比效果會稍遜於條形圖。

總結

棒棒糖圖就像數據可視化世界中的"少即是多"哲學體現。

它不是要取代傳統條形圖,而是為數據可視化工具箱增加了一個有價值的選項。

就像不同的畫筆適合不同的繪畫風格,不同的圖表類型也適合不同的數據故事。

棒棒糖圖的真正優勢在於它改變了數據的"講述方式"

它不説:"這是所有信息,你自己找重點",而是説:"看這裏,這些是關鍵點"。

這種焦點導向的特性,使得棒棒糖圖在現代快節奏的數據溝通中越來越受歡迎。

設計可視化時,我們不妨問問自己:我想要觀眾首先看到什麼?如果是精確的數值點和清晰的排名,那麼棒棒糖圖可能是你的理想選擇。

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.