华夫饼图是饼图的一种变体,一般由100个格子组成,一个格子代表1%。用不同颜色的格子区分不同的分类数据,以展示各部分在整体中的占比。尤其擅长展示部分在整体中的占比关系。
基于pywaffle
import matplotlib.pyplot as plt
from pywaffle import Waffle
# 自定义数据
data = {'Kevin': 10, 'Joseph': 7, 'Yan': 8}
# 基础华夫饼图
plt.figure(
FigureClass=Waffle,
rows=15,
columns=20,
values=data,
legend={'loc': 'upper left', 'bbox_to_anchor': (1.05, 1)},
)
plt.show()
自定义华夫饼图一般是结合使用场景对相关参数进行修改,并辅以其他的绘图知识。参数信息可以通过官网进行查看,其他的绘图知识则更多来源于实战经验,大家不妨将接下来的绘图作为一种学习经验,以便于日后总结。
更多用法可参考Basic Examples and Formats of Values[1]
import pandas as pd
import matplotlib.pyplot as plt
from pywaffle import Waffle
import numpy as np
# 自定义数据
data = {'Category 1': 15,
'Category 2': 30,
'Category 3': 10,
'Category 4': 25,
'Category 5': 20}
# 计算方块数量
total_icons = sum(data.values())
# 自定义颜色图标
fig = plt.figure(
FigureClass=Waffle,
rows=10,
values=data,
icons='star', # 修改icon
colors=["#FF5733", "#FFC300", "#900C3F", "#FF5733", "#C70039"], # 自定义颜色
legend={'loc': 'upper left', 'bbox_to_anchor': (1, 1)},
icon_legend=True,
figsize=(8, 4),
font_size = 18
)
plt.show()
3
# 自定义数据
data = {'Cat': 30, 'Dog': 16, 'Goat': 40}
# 计算比例
repartition = [f"{k} ({int(v / sum(data.values()) * 100)}%)"
for k, v in data.items()]
# 自定义图例
fig = plt.figure(
FigureClass=Waffle,
rows=10,
columns=15,
values=data,
title={
'label': 'A graph with the distribution in the legend',
'loc': 'left',
'fontdict': {
'fontsize': 12
}
},
labels=repartition,
legend={
'loc': 'lower left',
'bbox_to_anchor': (0, -0.15),
'ncol': len(data),
'fontsize': 12
}
)
plt.show()
# 自定义数据
data = {'labels': ['Car', 'Truck', 'Motorcycle'],
'Factory A': [32384, 13354, 5245],
'Factory B': [22147, 6678, 2156],
'Factory C': [8932, 3879, 896],
}
df = pd.DataFrame(data).set_index('labels')
# 图1-Factory A
plot1 = {'values': [value/1000
for value in data['Factory A']], # 计算方块数
'labels': [f"{index} ({value})"
for index, value in zip(df['Factory A'],df.index)],
'legend': {'loc': 'upper left', 'bbox_to_anchor': (1.05, 1), 'fontsize': 8},
'title': {'label': 'Vehicle Production of Factory A', 'loc': 'left', 'fontsize': 12}
}
# 图2-Factory B
plot2 = {'values': [value/1000
for value in data['Factory B']],
'labels': [f"{index} ({value})"
for index, value in zip(df['Factory B'],df.index)],
'legend': {'loc': 'upper left', 'bbox_to_anchor': (1.2, 1), 'fontsize': 8},
'title': {'label': 'Vehicle Production of Factory B', 'loc': 'left', 'fontsize': 12}
}
# 图3-Factory C
plot3 = {'values': [value/1000
for value in data['Factory C']],
'labels': [f"{index} ({value})"
for index, value in zip(df['Factory C'],df.index)],
'legend': {'loc': 'upper left', 'bbox_to_anchor': (1.3, 1), 'fontsize': 8},
'title': {'label': 'Vehicle Production of Factory C', 'loc': 'left', 'fontsize': 12}
}
fig = plt.figure(
FigureClass=Waffle,
plots={
311: plot1,
312: plot2,
313: plot3,
},
rows=5, # 行数,应用于所有子图
cmap_name="Accent", # 颜色
rounding_rule='ceil', # 更改舍入规则(向上取整),因此小于1000的值也有一块
figsize=(8, 6)
)
# 添加标题和注释信息
fig.suptitle('Vehicle Production by Vehicle Type', fontsize=14, fontweight='bold')
fig.supxlabel('1 block = 1000 vehicles',
fontsize=8,
x=0.14, # 轴位置
)
fig.set_facecolor('#EEEDE7')
plt.show()
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from pywaffle import Waffle
import pandas as pd
# 自定义数据
data = {
2018: [3032, 2892, 804],
2019: [4537, 3379, 1096],
2020: [8932, 3879, 896],
2021: [22147, 6678, 2156],
2022: [32384, 13354, 5245]
}
df = pd.DataFrame(data,
index=['car', 'truck', 'motorcycle'])
number_of_bars = len(df.columns) # 每年一个bar
# 初始化布局1*n的子图
fig, axs = plt.subplots(nrows=1,
ncols=number_of_bars,
figsize=(8,6),)
# 迭代每个bar
for i,ax in enumerate(axs):
col_name = df.columns[i]
values = df[col_name]
Waffle.make_waffle(
ax=ax, # 传参指定的ax
rows=20,
columns=5,
values=values,
)
plt.show()
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from pywaffle import Waffle
import pandas as pd
# 自定义数据
data = {
2018: [3032, 2892, 804],
2019: [4537, 3379, 1096],
2020: [8932, 3879, 896],
2021: [22147, 6678, 2156],
2022: [32384, 13354, 5245]
}
df = pd.DataFrame(data,
index=['car', 'truck', 'motorcycle'])
number_of_bars = len(df.columns) # 每年一个bar
# 初始化布局1*n的子图
fig, axs = plt.subplots(nrows=1,
ncols=number_of_bars,
figsize=(8,6),)
# 迭代每个bar
for i,ax in enumerate(axs):
col_name = df.columns[i]
values = df[col_name]
Waffle.make_waffle(
ax=ax,
rows=20,
columns=5,
values=values,
vertical=True, # 垂直堆叠
)
plt.show()
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from pywaffle import Waffle
import pandas as pd
# 自定义数据
data = {
2018: [3032, 2892, 804],
2019: [4537, 3379, 1096],
2020: [8932, 3879, 896],
2021: [22147, 6678, 2156],
2022: [32384, 13354, 5245]
}
df = pd.DataFrame(data,
index=['car', 'truck', 'motorcycle'])
number_of_bars = len(df.columns) # 每年一个bar
# 颜色
colors = ["darkred", "red", "darkorange"]
# 初始化布局1*n的子图
fig, axs = plt.subplots(nrows=1,
ncols=number_of_bars,
figsize=(8,6),)
# 迭代每个bar
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,
icons=['car-side', 'truck', 'motorcycle'], # 设置icon
font_size=12,
icon_legend=True,
legend={'loc': 'upper left', 'bbox_to_anchor': (1, 1)},
)
# 添加标题
fig.suptitle('Vehicle Production by Year and Vehicle Type',
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="Vehicle Types",
bbox_to_anchor=(1.04, 0.9))
plt.subplots_adjust(right=0.85)
plt.show()
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from pywaffle import Waffle
import pandas as pd
# 自定义数据
data = {
2018: [3032, 2892, 804],
2019: [4537, 3379, 1096],
2020: [8932, 3879, 896],
}
df = pd.DataFrame(data,
index=['car', 'truck', 'motorcycle'])
# 颜色
colors = ["darkred", "red", "darkorange"]
# 水平条形图:初始化布局1*n的子图(柱形图可以改一下布局,并改变下面的columns为rows)
fig, axs = plt.subplots(nrows=3,ncols=1,figsize=(12,8),)
# 迭代每个bar
for i,ax in enumerate(axs):
col_name = df.columns[i]
values = df[col_name]/1000
Waffle.make_waffle(
ax=ax,
columns=10, # 这里的数值设置为所有数据中最大的,避免华夫饼图自动堆叠
values=values,
title={"label": col_name, "loc": "left"},
icons=['car-side', 'truck', 'motorcycle'], # 设置icon
colors=colors,
rounding_rule='ceil', # 更改舍入规则(向上取整),因此小于1000的值也有一块
block_arranging_style='new-line', # 每一类从下一行开始绘制
vertical=True, # 垂直方向
interval_ratio_x=0.1, # 调整水平的格子间距比率
interval_ratio_y=0.1, # 调整垂直的格子间距比率
starting_location='NW', # 从左上角开始绘制
)
# 添加标题
fig.suptitle('Vehicle Production by Year and Vehicle Type',
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="Vehicle Types",
bbox_to_anchor=(1.04, 0.9))
plt.subplots_adjust(right=0.85)
plt.show()
以上通过pywaffle快速绘制华夫饼图。并通过修改参数或者辅以其他绘图知识自定义各种各样的华夫饼图来适应相关使用场景。
共勉~
[1]
Basic Examples and Formats of Values: https://pywaffle.readthedocs.io/en/latest/examples/formats_of_values.html