華夫餅圖Waffle chart是一種獨(dú)特而直觀的圖表,用于表示分類數(shù)據(jù)。它采用網(wǎng)格狀排列的等大小方格或矩形,每個(gè)方格或矩形分配不同的顏色或陰影來表示不同的類別。這種可視化方法有效地傳達(dá)了每個(gè)類別在整個(gè)數(shù)據(jù)集中的相對(duì)比例。本文介紹如何使用基于Python的PyWaffle庫繪制華夫餅圖。PyWaff
華夫餅圖Waffle chart是一種獨(dú)特而直觀的圖表,用于表示分類數(shù)據(jù)。它采用網(wǎng)格狀排列的等大小方格或矩形,每個(gè)方格或矩形分配不同的顏色或陰影來表示不同的類別。這種可視化方法有效地傳達(dá)了每個(gè)類別在整個(gè)數(shù)據(jù)集中的相對(duì)比例。本文介紹如何使用基于Python的PyWaffle庫繪制華夫餅圖。PyWaffle開源倉庫地址見: PyWaffle ,PyWaffle官方文檔見: PyWaffle-docs 。本文代碼下載地址: Python-Study-Notes 。
PyWaffle安裝方式如下:
pip install -U pywaffle
# PyWaffle庫依賴于matplotlib繪制圖片
import matplotlib.pyplot as plt
from pywaffle import Waffle
PyWaffle庫通過其Waffle類提供了一種便捷的方式來創(chuàng)建華夫餅圖。每個(gè)類別的方格占比可以通過參數(shù)values進(jìn)行設(shè)置,數(shù)據(jù)可以是列表、字典和Pandas.DataFrame結(jié)構(gòu)。然后可以使用rows和columns參數(shù)來定制行數(shù)和列數(shù)。只需要指定其中一個(gè)參數(shù),另一個(gè)參數(shù)可以根據(jù)values的總和推斷出來。
# 新建繪圖圖像
fig = plt.figure(
FigureClass=Waffle,
rows=5,
# columns=10,
values=[30, 16, 4]
)
# 保存結(jié)果
# fig.savefig("plot.png", bbox_inches="tight")
plt.show()
如果value參數(shù)輸入的是比例值,則必須設(shè)置rows和columns屬性來定義值的顯示方式。
fig = plt.figure(
FigureClass=Waffle,
rows=2,
columns=5,
values=[0.2, 0.5, 0.3]
)
plt.show()
如果values總和與rows*columns的結(jié)果不一致,Waffle類將values解釋為各部分的相對(duì)比例。
fig = plt.figure(
FigureClass=Waffle,
rows=5,
columns=5,
values=[30, 16, 4]
)
plt.show()
當(dāng)字典傳遞給values時(shí),鍵將用作標(biāo)簽并顯示在圖例中,注意圖例會(huì)默認(rèn)顯示。
plt.figure(
FigureClass=Waffle,
rows=5,
values={'Cat': 30, 'Dog': 16, 'Bird': 4},
legend={'loc': 'upper left', 'bbox_to_anchor': (1, 1), 'frameon': False} # 修改圖例
)
plt.show()
不顯示圖例。
fig = plt.figure(
FigureClass=Waffle,
rows=5,
values={'Cat': 30, 'Dog': 16, 'Bird': 4},
legend={'loc': 'upper left', 'bbox_to_anchor': (1, 1), 'frameon': False} # 修改圖例
)
# 移除legend
fig.axes[0].get_legend().remove()
plt.show()
如果values的總和與rows*columns的結(jié)果不一致,Waffle類將解釋values為各部分的相對(duì)比例。如下所示各個(gè)類別方塊數(shù)輸出為小數(shù),小數(shù)位的取舍會(huì)導(dǎo)致不同的展示效果:
# nearest, ceil or floor
import numpy as np
target = {'Cat': 48, 'Dog': 46, 'Bird': 3, 'Fish': 9}
values = np.array(list(target.values()))
values_ratio = values /sum(values)
# 華夫餅圖結(jié)構(gòu)
row = 2
col = 5
# 各個(gè)類別方塊數(shù)
values_ratio * row *col
array([4.52830189, 4.33962264, 0.28301887, 0.8490566 ])
為此,Waffle類通過rounding_rule參數(shù)來處理小數(shù)位取舍問題。rounding_rule可選值為nearest(默認(rèn)), ceil或floor。具體如下:
nearest
nearest表示將方塊的數(shù)值四舍五入到最接近的整數(shù)。
# 各個(gè)類別方塊數(shù)
np.round(values_ratio * row *col, 0).astype(int)
array([5, 4, 0, 1])
np.round(values_ratio*10,0).astype(int)
plt.figure(
FigureClass=Waffle,
rows=2,
columns=5,
values=target,
rounding_rule='nearest', # 默認(rèn)值
legend={'loc': 'upper left', 'bbox_to_anchor': (1, 1), 'frameon': False} # 修改圖例
)
plt.show()
ceil
ceil表示將方塊的數(shù)值向上舍入到最接近的整數(shù)。然而,在nearest和ceil模式下,方塊的總和可能會(huì)超過華夫餅圖的預(yù)設(shè)長度,超出預(yù)設(shè)長度的方塊將不會(huì)顯示。這也意味著,輸入類別位置越靠后,其方塊顯示的數(shù)值越可能不準(zhǔn)確。
# 各個(gè)類別方塊數(shù)
np.ceil(values_ratio * row *col).astype(int)
array([5, 5, 1, 1])
np.round(values_ratio*10,0).astype(int)
plt.figure(
FigureClass=Waffle,
rows=2,
columns=5,
values=target,
rounding_rule='ceil', # 默認(rèn)值
legend={'loc': 'upper left', 'bbox_to_anchor': (1, 1), 'frameon': False} # 修改圖例
)
plt.show()
floor
floor表示將方塊的數(shù)值向下舍入到最接近的整數(shù),由于這種舍入方式的特性,繪制的方塊數(shù)可少于預(yù)設(shè)的數(shù)量。
# 各個(gè)類別方塊數(shù)
np.floor(values_ratio * row *col).astype(int)
array([4, 4, 0, 0])
np.round(values_ratio*10,0).astype(int)
plt.figure(
FigureClass=Waffle,
rows=2,
columns=5,
values=target,
rounding_rule='floor', # 默認(rèn)值
legend={'loc': 'upper left', 'bbox_to_anchor': (1, 1), 'frameon': False} # 修改圖例
)
plt.show()
如果想要在華夫餅圖中完整顯示所有類別,但又不希望方塊數(shù)量過多,一種有效的方法是只設(shè)定rows或columns中的一個(gè)參數(shù),然后將每個(gè)類別的數(shù)值除以最小類別的數(shù)值,以確保最少類別的方塊數(shù)量為1,同時(shí)將其他類別的數(shù)值顯示為相對(duì)于最少類別的比例。
target_ = target.copy()
# 找到最小值
min_value = min(target_.values())
# 更新字典中每個(gè)鍵對(duì)應(yīng)的值
target_ = {key: int(value / min_value) for key, value in target.items()}
print(target_)
{'Cat': 16, 'Dog': 15, 'Bird': 1, 'Fish': 3}
np.round(values_ratio*10,0).astype(int)
plt.figure(
FigureClass=Waffle,
rows=4,
values=target_,
legend={'loc': 'upper left', 'bbox_to_anchor': (1, 1), 'frameon': False} # 修改圖例
)
plt.show()
標(biāo)題、標(biāo)簽和圖例
data = {'Cat': 30, 'Dog': 16, 'Bird': 4}
fig = plt.figure(
FigureClass=Waffle,
rows=5,
columns=10,
values = data,
title={
'label': 'Example plot',
'loc': 'center',
'fontdict': {
'fontsize': 20
}
},
labels=[f"{k} ({int(v / sum(data.values()) * 100)}%)" for k, v in data.items()],
legend={
#'labels': [f"{k} ({v}%)" for k, v in data.items()], # labels可以在legend中設(shè)置
'loc': 'lower left',
'bbox_to_anchor': (0, -0.2),
'ncol': len(data),
'framealpha': 0,
'fontsize': 12
},
# 設(shè)置顏色條,支持Pastel1, Pastel2, Paired, Accent, Dark2, Set1, Set2, Set3, tab10, tab20, tab20b, tab20c
cmap_name="Accent",
facecolor='#DDDDDD', # 繪圖背景色
# 也可以單獨(dú)設(shè)置顏色
# colors=["#232066", "#983D3D", "#DCB732", "F12F34"]
)
方塊寬高比設(shè)置
參數(shù)block_aspect_ratio通過更改塊的寬度與塊的高度之比來控制方塊的形狀。默認(rèn)block_aspect_ratio為1,也就是每個(gè)方塊都是正方形。
fig = plt.figure(
FigureClass=Waffle,
rows=5,
values=[30, 16, 4],
block_aspect_ratio=1.618
)
方塊間距控制
參數(shù)interval_ratio_x和interval_ratio_y分別負(fù)責(zé)調(diào)節(jié)塊之間的水平和垂直間距。具體來說,interval_ratio_x代表了塊之間的水平間距與塊寬度的比率,而interval_ratio_y則反映了塊之間的垂直間距與塊高度的比率。
fig = plt.figure(
FigureClass=Waffle,
rows=5,
values=[30, 16, 4],
interval_ratio_x=1,
interval_ratio_y=0.5
)
起始方塊繪圖位置
starting_location用于設(shè)置起始方塊的位置。這個(gè)參數(shù)可輸入包括 "NW(西北角、左上角)"、"SW(默認(rèn)值,西南角,右下角)"、"NE(東北角,右上角)" 和 "SE(東南角,右下角)"。
fig = plt.figure(
FigureClass=Waffle,
rows=5,
values=[30, 16, 4],
starting_location='SE'
)
繪圖方向
默認(rèn)情況下PyWaffle逐列繪制方塊,因此類別是按水平方向排列繪制的,如果按行繪制方塊,則設(shè)置vertical參數(shù)為True。
fig = plt.figure(
FigureClass=Waffle,
rows=5,
values=[30, 16, 4],
vertical=True
)
類別方塊排列方式
block_arranging_style參數(shù)用于控圖中各類別方塊的排列方式,具體如下:
# new-line排列
fig = plt.figure(
FigureClass=Waffle,
rows=5,
values=[12, 22, 20, 4],
vertical=True,
block_arranging_style='new-line'
)
# snake排列
fig = plt.figure(
FigureClass=Waffle,
rows=5,
values=[12, 22, 20, 4],
block_arranging_style='snake'
)
子圖繪制
PyWaffle可以通過添加子圖的方式,實(shí)現(xiàn)在同一張圖中顯示多個(gè)華夫餅圖。以下是示例:
import pandas as pd
# 創(chuàng)建一個(gè)產(chǎn)量表格
data = pd.DataFrame(
{
'labels': ['Car', 'Truck', 'Motorcycle'],
'Factory A': [44183, 12354, 3246],
'Factory B': [29198, 7678, 2556],
'Factory C': [9013, 4079, 996],
},
).set_index('labels')
fig = plt.figure(
FigureClass=Waffle,
plots={
311: { # 311數(shù)字對(duì)應(yīng)于 matplotlib中subplot 的位置編碼方式,311表示一個(gè)三行一列的布局中的第一個(gè)子圖
'values': data['Factory A'] / 1000, # 將實(shí)際數(shù)字轉(zhuǎn)換為合理的塊數(shù)
'labels': [f"{k} ({v})" for k, v in data['Factory A'].items()],
'legend': {'loc': 'upper left', 'bbox_to_anchor': (1.05, 1), 'fontsize': 8},
'title': {'label': 'Vehicle Production of Factory A', 'loc': 'left', 'fontsize': 12}
},
312: {
'values': data['Factory B'] / 1000,
'labels': [f"{k} ({v})" for k, v in data['Factory B'].items()],
'legend': {'loc': 'upper left', 'bbox_to_anchor': (1.2, 1), 'fontsize': 8},
'title': {'label': 'Vehicle Production of Factory B', 'loc': 'left', 'fontsize': 12}
},
313: {
'values': data['Factory C'] / 1000,
'labels': [f"{k} ({v})" for k, v in data['Factory C'].items()],
'legend': {'loc': 'upper left', 'bbox_to_anchor': (1.3, 1), 'fontsize': 8},
'title': {'label': 'Vehicle Production of Factory C', 'loc': 'left', 'fontsize': 12}
},
},
rows=5, # 應(yīng)用于所有子圖的外部參數(shù),與下面相同
cmap_name="Paired",
rounding_rule='ceil',
figsize=(5, 5)
)
fig.suptitle('Vehicle Production by Vehicle Type', fontsize=14, fontweight='bold')
# 說明1個(gè)方塊代表多少車輛
fig.supxlabel('1 block = 1000 vehicles', fontsize=8, ha='right')
Text(0.5, 0.01, '1 block = 1000 vehicles')
現(xiàn)有軸繪圖
Pywaffle提供Waffle.make_waffle方法來在現(xiàn)有的matplotlib軸上繪圖,而不需要重新初始化Waffle實(shí)例。
fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_title("Axis Title", loc= "right")
ax.set_aspect(aspect="equal")
Waffle.make_waffle(
ax=ax, # 利用現(xiàn)有繪圖對(duì)象
rows=5,
columns=10,
values=[30, 16, 4],
title={"label": "Waffle Title", "loc": "left"}
)
此外可以利用make_waffle與已定義坐標(biāo)軸來顯示多個(gè)數(shù)據(jù)結(jié)果。
import matplotlib.patches as mpatches
data = {
2021: [175, 139, 96],
2022: [232, 187, 126],
2023: [345, 278, 195],
2024: [456, 389, 267]
}
df = pd.DataFrame(data,index=['cat', 'dog', 'cow'])
number_of_bars = len(df.columns)
colors = ["darkred", "red", "darkorange"]
# Init the whole figure and axes
fig, axs = plt.subplots(nrows=1,
ncols=number_of_bars,
figsize=(8,6),)
# Iterate over each bar and create it
for i,ax in enumerate(axs):
col_name = df.columns[i]
values = df[col_name]/1000
Waffle.make_waffle(
ax=ax,
rows=20,
columns=5,
values=values,
title={"label": col_name, "loc": "left"},
colors=colors,
vertical=True,
font_size=12
)
fig.suptitle('Animal Type Data Display',
fontsize=14, fontweight='bold')
legend_labels = df.index
legend_elements = [mpatches.Patch(color=colors[i],
label=legend_labels[i]) for i in range(len(colors))]
fig.legend(handles=legend_elements,
loc="upper right",
title="Animal Types",
bbox_to_anchor=(1.04, 0.5),
framealpha = 0,
fontsize=12)
plt.subplots_adjust(right=0.85)
plt.show()
添加其他matplotlib繪圖組件
fig = plt.figure(
FigureClass=Waffle,
rows=5,
values=[30, 16, 4]
)
fig.text(
x=0.5,
y=0.5,
s="hello world!",
ha="center",
va="center",
rotation=30,
fontsize=40,
color='black',
alpha=0.3,
bbox={
'boxstyle': 'square',
'lw': 3,
'ec': 'gray',
'fc': (0.9, 0.9, 0.9, 0.5),
'alpha': 0.3
}
)
Text(0.5, 0.5, 'hello world!')
Pywaffle支持字符和圖標(biāo)來變換方格樣式。
字符
Pywaffe允許一個(gè)或多個(gè)Unicode字符來替換華夫餅圖中方格的樣式?捎玫腢nicode字符見: unicode-table 。
fig = plt.figure(
FigureClass=Waffle,
rows=5,
values=[30, 16, 4],
colors=["#4C8CB5", "#B7CBD7", "#C0C0C0"],
characters='??', # 使用兩個(gè)Unicode字符來展示
font_size=24
)
圖標(biāo)
Pywaffe允許 fontawesome 中的圖標(biāo)來替換華夫餅圖中方格的樣式。 注意,如果是Windows系統(tǒng),需要matplotlib 3.5.2及以下版本才能支持該功能 。Linux系統(tǒng)對(duì)matplotlib版本沒有限制。
import matplotlib
# 查看matplotlib版本
matplotlib.__version__
'3.8.3'
圖標(biāo)設(shè)置方式如下:
fig = plt.figure(
FigureClass=Waffle,
rows=5,
values=[30, 16, 4],
colors=["#FD5C46", "#9DDF3D", "#AFFBC1"], # 設(shè)置顏色
icons='person', # 設(shè)置icon
font_size= 30 # 圖表大小
)
為每個(gè)類別設(shè)置對(duì)應(yīng)的圖標(biāo)的方式如下所示:
fig = plt.figure(
FigureClass=Waffle,
rows=5,
values={'Cat': 30, 'Dog': 16, 'Cow': 4},
colors=["#000077", "#139900", "#771234"],
icons=['cat', 'dog', 'cow'],
font_size=20,
icon_legend=True, # 替換legend的標(biāo)簽為icon
legend={
'labels': ['CAT', 'DOG', 'COW'],
'loc': 'upper left',
'bbox_to_anchor': (1, 1),
'frameon': False,
}
)
進(jìn)一步設(shè)置圖標(biāo)的樣式,注意并非每個(gè)FontAwesome都擁有不同的圖標(biāo)樣式,因此在編寫代碼時(shí)務(wù)必進(jìn)行檢查。
fig = plt.figure(
FigureClass=Waffle,
rows=5,
values=[30, 16, 4],
colors=["#FFA500", "#4384FF", "#C0C0C0"],
icons=['sun', 'cloud-showers-heavy', 'font-awesome'],
icon_size=20,
icon_style=['regular', 'solid', 'brands'],
icon_legend=False,
legend={
'labels': ['Sun', 'Shower', 'Flag'],
'loc': 'upper left',
'bbox_to_anchor': (1, 1)
}
)
機(jī)器學(xué)習(xí):神經(jīng)網(wǎng)絡(luò)構(gòu)建(下)
閱讀華為Mate品牌盛典:HarmonyOS NEXT加持下游戲性能得到充分釋放
閱讀實(shí)現(xiàn)對(duì)象集合與DataTable的相互轉(zhuǎn)換
閱讀鴻蒙NEXT元服務(wù):論如何免費(fèi)快速上架作品
閱讀算法與數(shù)據(jù)結(jié)構(gòu) 1 - 模擬
閱讀5. Spring Cloud OpenFeign 聲明式 WebService 客戶端的超詳細(xì)使用
閱讀Java代理模式:靜態(tài)代理和動(dòng)態(tài)代理的對(duì)比分析
閱讀Win11筆記本“自動(dòng)管理應(yīng)用的顏色”顯示規(guī)則
閱讀本站所有軟件,都由網(wǎng)友上傳,如有侵犯你的版權(quán),請發(fā)郵件[email protected]
湘ICP備2022002427號(hào)-10 湘公網(wǎng)安備:43070202000427號(hào)© 2013~2025 haote.com 好特網(wǎng)