[python] 基于PyWaffle库绘制华夫饼图

华夫饼图Waffle chart是一种独特而直观的图表,用于表示分类数据。它采用网格状排列的等大小方格或矩形,每个方格或矩形分配不同的颜色或阴影来表示不同的类别。这种可视化方法有效地传达了每个类别在整个数据集中的相对比例。本文介绍如何使用基于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

文章目录

  • 1 使用简介
    • 1.1 基本使用
      • 1.1.1 基础绘图
      • 1.1.2 类别比例设置
    • 1.2 样式设置
      • 1.2.1 展示效果设置
      • 1.2.2 绘图框架自定义
      • 1.2.3 方格样式变换
  • 2 参考

1 使用简介

1.1 基本使用

1.1.1 基础绘图

PyWaffle库通过其Waffle类提供了一种便捷的方式来创建华夫饼图。每个类别的方格占比可以通过参数values进行设置,数据可以是列表、字典和Pandas.DataFrame结构。然后可以使用rows和columns参数来定制行数和列数。只需要指定其中一个参数,另一个参数可以根据values的总和推断出来。

# 新建绘图图像
fig = plt.figure(FigureClass=Waffle,rows=5,# columns=10,values=[30, 16, 4]
)
# 保存结果
# fig.savefig("plot.png", bbox_inches="tight")
plt.show()

png

如果value参数输入的是比例值,则必须设置rows和columns属性来定义值的显示方式。

fig = plt.figure(FigureClass=Waffle,rows=2,columns=5,values=[0.2, 0.5, 0.3]
)
plt.show()

png

如果values总和与rows*columns的结果不一致,Waffle类将values解释为各部分的相对比例。

fig = plt.figure(FigureClass=Waffle,rows=5,columns=5,values=[30, 16, 4]
)
plt.show()

png

当字典传递给values时,键将用作标签并显示在图例中,注意图例会默认显示。

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()

png

不显示图例。

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()

png

1.1.2 类别比例设置

如果values的总和与rows*columns的结果不一致,Waffle类将解释values为各部分的相对比例。如下所示各个类别方块数输出为小数,小数位的取舍会导致不同的展示效果:

# nearest, ceil or floorimport numpy as nptarget = {'Cat': 48, 'Dog': 46, 'Bird': 3, 'Fish': 9}values = np.array(list(target.values()))values_ratio = values /sum(values)
# 华夫饼图结构
row = 2
col = 5
# 各个类别方块数
values_ratio * row *col
array([4.52830189, 4.33962264, 0.28301887, 0.8490566 ])

为此,Waffle类通过rounding_rule参数来处理小数位取舍问题。rounding_rule可选值为nearest(默认), ceil或floor。具体如下:

nearest

nearest表示将方块的数值四舍五入到最接近的整数。

# 各个类别方块数
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', # 默认值legend={'loc': 'upper left', 'bbox_to_anchor': (1, 1), 'frameon': False} # 修改图例
)
plt.show()

png

ceil

ceil表示将方块的数值向上舍入到最接近的整数。然而,在nearest和ceil模式下,方块的总和可能会超过华夫饼图的预设长度,超出预设长度的方块将不会显示。这也意味着,输入类别位置越靠后,其方块显示的数值越可能不准确。

# 各个类别方块数
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', # 默认值legend={'loc': 'upper left', 'bbox_to_anchor': (1, 1), 'frameon': False} # 修改图例
)
plt.show()

png

floor

floor表示将方块的数值向下舍入到最接近的整数,由于这种舍入方式的特性,绘制的方块数可少于预设的数量。

# 各个类别方块数
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', # 默认值legend={'loc': 'upper left', 'bbox_to_anchor': (1, 1), 'frameon': False} # 修改图例
)
plt.show()

png

如果想要在华夫饼图中完整显示所有类别,但又不希望方块数量过多,一种有效的方法是只设定rows或columns中的一个参数,然后将每个类别的数值除以最小类别的数值,以确保最少类别的方块数量为1,同时将其他类别的数值显示为相对于最少类别的比例。

target_ = target.copy()
# 找到最小值
min_value = min(target_.values())# 更新字典中每个键对应的值
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()

png

1.2 样式设置

1.2.1 展示效果设置

标题、标签和图例

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中设置'loc': 'lower left','bbox_to_anchor': (0, -0.2),'ncol': len(data),'framealpha': 0,'fontsize': 12},# 设置颜色条,支持Pastel1, Pastel2, Paired, Accent, Dark2, Set1, Set2, Set3, tab10, tab20, tab20b, tab20ccmap_name="Accent",facecolor='#DDDDDD',  # 绘图背景色# 也可以单独设置颜色# colors=["#232066", "#983D3D", "#DCB732", "F12F34"])

png

方块宽高比设置

参数block_aspect_ratio通过更改块的宽度与块的高度之比来控制方块的形状。默认block_aspect_ratio为1,也就是每个方块都是正方形。

fig = plt.figure(FigureClass=Waffle,rows=5,values=[30, 16, 4],block_aspect_ratio=1.618
)

png

方块间距控制

参数interval_ratio_x和interval_ratio_y分别负责调节块之间的水平和垂直间距。具体来说,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
)

png

起始方块绘图位置

starting_location用于设置起始方块的位置。这个参数可输入包括 “NW(西北角、左上角)”、“SW(默认值,西南角,右下角)”、“NE(东北角,右上角)” 和 “SE(东南角,右下角)”。

fig = plt.figure(FigureClass=Waffle,rows=5,values=[30, 16, 4],starting_location='SE'
)

png

绘图方向

默认情况下PyWaffle逐列绘制方块,因此类别是按水平方向排列绘制的,如果按行绘制方块,则设置vertical参数为True。

fig = plt.figure(FigureClass=Waffle,rows=5,values=[30, 16, 4],vertical=True
)

png

类别方块排列方式

block_arranging_style参数用于控图中各类别方块的排列方式,具体如下:

  • normal: 默认方式,方块会按照常规的网格模式进行排列。
  • new-line: 每个类别的方块都会从新的一行开始排列。这意味着,如果你有多个类别,每行只有一个类别的图标。
  • snake: 方块会按照“蛇形”或“之字形”的模式进行排列。
# new-line排列
fig = plt.figure(FigureClass=Waffle,rows=5,values=[12, 22, 20, 4],vertical=True,block_arranging_style='new-line'
)

png

# snake排列
fig = plt.figure(FigureClass=Waffle,rows=5,values=[12, 22, 20, 4],block_arranging_style='snake'
)

png

1.2.2 绘图框架自定义

子图绘制

PyWaffle可以通过添加子图的方式,实现在同一张图中显示多个华夫饼图。以下是示例:

import pandas as pd
# 创建一个产量表格
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数字对应于 matplotlib中subplot 的位置编码方式,311表示一个三行一列的布局中的第一个子图'values': data['Factory A'] / 1000,   # 将实际数字转换为合理的块数'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,   # 应用于所有子图的外部参数,与下面相同cmap_name="Paired", rounding_rule='ceil', figsize=(5, 5)
)fig.suptitle('Vehicle Production by Vehicle Type', fontsize=14, fontweight='bold')
# 说明1个方块代表多少车辆
fig.supxlabel('1 block = 1000 vehicles', fontsize=8, ha='right')
Text(0.5, 0.01, '1 block = 1000 vehicles')

png

现有轴绘图

Pywaffle提供Waffle.make_waffle方法来在现有的matplotlib轴上绘图,而不需要重新初始化Waffle实例。

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,  # 利用现有绘图对象rows=5, columns=10, values=[30, 16, 4], title={"label": "Waffle Title", "loc": "left"}
)

png

此外可以利用make_waffle与已定义坐标轴来显示多个数据结果。

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]/1000Waffle.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()

png

添加其他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!')

png

1.2.3 方格样式变换

Pywaffle支持字符和图标来变换方格样式。

字符

Pywaffe允许一个或多个Unicode字符来替换华夫饼图中方格的样式。可用的Unicode字符见:unicode-table。

fig = plt.figure(FigureClass=Waffle,rows=5,values=[30, 16, 4],colors=["#4C8CB5", "#B7CBD7", "#C0C0C0"],characters='😊Ã', # 使用两个Unicode字符来展示font_size=24
)

png

图标

Pywaffe允许fontawesome中的图标来替换华夫饼图中方格的样式。注意,如果是Windows系统,需要matplotlib 3.5.2及以下版本才能支持该功能。Linux系统对matplotlib版本没有限制。

import matplotlib
# 查看matplotlib版本
matplotlib.__version__
'3.8.3'

图标设置方式如下:

fig = plt.figure(FigureClass=Waffle,rows=5,values=[30, 16, 4],colors=["#FD5C46", "#9DDF3D", "#AFFBC1"],  # 设置颜色icons='person', # 设置iconfont_size= 30 # 图表大小
)

png

为每个类别设置对应的图标的方式如下所示:

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的标签为iconlegend={'labels': ['CAT', 'DOG', 'COW'], 'loc': 'upper left', 'bbox_to_anchor': (1, 1),'frameon': False,}
)

png

进一步设置图标的样式,注意并非每个FontAwesome都拥有不同的图标样式,因此在编写代码时务必进行检查。

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)}
)

png

2 参考

  • PyWaffle
  • PyWaffle-docs
  • unicode-table
  • fontawesome

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/660313.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

二阶逻辑回归

使用此种二阶函数,可以很好的补齐一个圆 这里涉及到一些函数的原理 http://链接: https://pan.baidu.com/s/1qftR1DY1LscbwE_uSje4dQ 提取码: sm88 复制这段内容后打开百度网盘手机App,操作更方便哦 数据集下载

[1688]jsp工资投放管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 工资投放管理系统是一套完善的java web信息管理系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql5.0…

linux 搭建知识库文档系统 mm-wiki

目录 一、前言 二、常用的知识库文档工具 2.1 PingCode 2.2 语雀 2.3 Tettra 2.4 Zoho Wiki 2.5 Helpjuice 2.6 SlimWiki 2.7 Document360 2.8 MM-Wiki 2.9 其他工具补充 三、MM-Wiki 介绍 3.1 什么是MM-Wiki 3.2 MM-Wiki 特点 四、搭建MM-Wiki前置准备 4.1 前置…

Unity类银河恶魔城学习记录15-5,6 p157 Audio time limiter p158 Area sound

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释,可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili​​ AreaSound.cs using System.Collections; using System.Collections.G…

Android4.4真机移植过程笔记(三)

如果文章字体看得不是很清楚,大家可以下载pdf文档查看,文档已上传~oo~ 7、安装加密APK 需要修改文件如下: 相对Android4.2改动还是蛮大的,有些文件连路径都变了: //Android4.2 1、frameworks/native/libs…

ctfshow——SQL注入

文章目录 SQL注入基本流程普通SQL注入布尔盲注时间盲注报错注入——extractvalue()报错注入——updataxml()Sqlmap的用法 web 171——正常联合查询web 172——查看源代码、联合查询web 173——查看源代码、联合查询web 174——布尔盲注web 176web 177——过滤空格web 178——过…

安卓获取SHA

1:安卓通过签名key获取SHA 方式有两种, 1、电脑上来存在eclipse的用户或正在使用此开发工具的用户就简单了,直接利用eclipse 走打包流程,再打包的时候选择相应的签名,那么在当前面板的下面便会出现签名的相关信息。 2、…

「C/C++ 01」计算结构体/类的大小和内存对齐

目录 一、计算结构体的大小 二、计算类的大小 三、内存对齐 一、计算结构体的大小 计算结构体的大小要遵循内存对齐规则:即从第二个成员变量开始,起始位置要计算,在自己的大小和默认对齐数(VS编译器中默认对齐数为8)中选择较小的那个&#x…

CSS样式特异性5层次详解

你好,我是云桃桃。 一个希望帮助更多朋友快速入门 WEB 前端的程序媛。 云桃桃-大专生,一枚程序媛,感谢关注。回复 “前端基础题”,可免费获得前端基础 100 题汇总,回复 “前端工具”,可获取 Web 开发工具合…

基于OpenCv的图像基本操作

⚠申明: 未经许可,禁止以任何形式转载,若要引用,请标注链接地址。 全文共计3077字,阅读大概需要3分钟 🌈更多学习内容, 欢迎👏关注👀【文末】我的个人微信公众号&#xf…

「C/C++ 01」类型转换与整型提升

目录 一、类型转换和截断问题 1. 隐式类型转换 2. 强制类型转换 3. 截断问题 二、整型提升 0. 算数表达式的计算过程 1. 整型提升是什么? 2. 为什么要整型提升? 3. 如何进行整型提升 4. 唯一的注意事项 5. 通过在vs中的监视窗口来观察整型提升 6. 整型…

PotatoPie 4.0 实验教程(36) —— FPGA实现摄像头图像二值化开运算效果

手机扫码 链接直达 https://item.taobao.com/item.htm?ftt&id776516984361 什么是图像开运算,有什么作用? 图像开运算是数学形态学中的一种图像处理操作,它由两个基本操作组成:腐蚀(Erosion)和膨胀…