首页编程开发Matplotlib【数据可视化(Matplo...

【数据可视化(Matplotlib篇)】37.绘制饼图pie()

本系列文章配套代码获取有以下两种途径:

  • 通过百度网盘获取:
链接:https://pan.baidu.com/s/1jG-rGG4QMuZu0t0kEEl7SA?pwd=mnsj 提取码:mnsj
  • 前往GitHub获取
https://github.com/returu/Data_Visualization





在数据可视化中,饼图因其直观展示各部分占比关系的特点,成为最常用的图表类型之一。无论是展示销售份额、用户分布还是预算分配,饼图都能清晰呈现整体与部分的关系。
01

函数语法


Matplotlib barh()函数专门用于绘制长条图(柱状图),其函数语法如下:
plt.pie(x, *, explode=None, labels=None, colors=None        autopct=None, pctdistance=0.6, shadow=False        labeldistance=1.1, startangle=0, radius=1        counterclock=True, wedgeprops=None, textprops=None        center=(00), frame=False, rotatelabels=False        normalize=True, hatch=None, data=None)
其中:
  • x:数据值数组,表示每个扇形的数值,并会自动转换为百分比
  • explode:用于突出显示特定扇区。通过指定偏移量使某些扇区远离中心,例如explode=[0,0.1,0,0]将第二个扇区向外偏移0.1。
  • labels:每个扇区的标签,通常显示在外部。
  • colors:扇区的填充颜色(列表),可以是颜色名称或十六进制代码。
  • autopct:控制百分比标签的格式,如‘%1.1f%%’表示保留一位小数。
  • pctdistance:百分比标签距离圆心的距离,默认0.6。
  • shadow:是否添加阴影,增强立体感
  • labeldistance:标签距离圆心的距离,默认1.1。小于1时标签会显示在扇区内部。
  • startangle第一个扇形的起始角度(度),默认从x轴正方向逆时针开始。startangle=90y轴正方向开始。
  • radius:饼图的半径,控制整体大小。
  • counterclock:布尔值,决定饼图是逆时针(True)还是顺时针(False)绘制。
  • wedgeprops扇区属性字典,用于设置扇区的属性,例如线宽、透明度等,例如wedgeprops={‘linewidth’:2, ‘edgecolor’:’black’}设置边框线宽和颜色
  • textprops文本属性字典,用于设置文本(标签和百分比)的属性,如字体大小、颜色,例如textprops={‘fontsize’:12, ‘color’:’red’}调整标签字体大小和颜色
  • center:饼图的中心位置,默认为(0,0)。
  • frame:布尔值,是否显示坐标轴框架,默认False
  • rotatelabels:布尔值,是否旋转标签以适应角度,默认False
  • normalize:是否归一化数据,True表示将数据总和归一化为1,False则按原始数据绘制。
  • hatch:为扇区添加纹理填充,如‘/’、’\’、’*’等。
  • data数据映射参数,用于复杂场景(如Pandas DataFrame集成)

通过调整这些参数,可以灵活控制饼的视觉效果。

plt.figure(figsize=(8,6))
plt.pie(
        x=[21, 35, 19, 20],  # 饼图各扇形的数值(会自动计算占比)
        labels=['类别A''类别B''类别C''类别D'],  # 每个扇形的标签文本
        colors=['#FF9999','#66B2FF','#99FF99','#FFCC99'],  # 自定义各扇形颜色
        autopct='%1.2f%%',  # 显示百分比,保留2位小数
        pctdistance=0.7,  # 百分比文本与圆心的距离(相对半径的比例)
        labeldistance=1.0,  # 标签文本与圆心的距离(相对半径的比例)
        explode=(0, 0.1, 0, 0),  # 第二个扇形(类别B)向外突出0.1单位
        shadow=True,  # 为饼图添加阴影效果,增强立体感
        startangle=90,  # 饼图起始角度设为90度(从y轴正方向开始绘制)
        # 设置扇形边框样式:黑色边框、线宽1.2、虚线样式
        wedgeprops={'edgecolor':'black''linewidth':1.2,'linestyle''--'},
        # 设置文本样式:字体大小14、红色、粗体
        textprops={'fontsize': 14, 'color''red','weight''bold'},
        rotatelabels=True  # 标签文本按扇形角度旋转,避免重叠
       )

plt.title('饼图绘制')
# 保证饼图为正圆形(否则可能因坐标轴比例显示为椭圆)
plt.axis('equal'
plt.show()

可视化结果如下图所示:

plt.pie() 函数的返回值是一个包含三个元素的元组,它们分别代表了饼图中不同组件的对象,方便我们进行更细致的样式调整和定制。

  • wedges:是一个 matplotlib.patches.Wedge 对象的列表,每个对象对应饼图中的一个扇形。可以通过该列表对单个扇形进行样式修改(如颜色、边框等)。

  • texts:是一个 matplotlib.text.Text 对象的列表,对应通过 labels 参数设置的标签文本。可用于调整标签的字体、位置等属性。

  • autotexts:是一个 matplotlib.text.Text 对象的列表(若未设置 autopct 则为 None),对应扇形内部的百分比文本。可用于修改百分比的显示样式。

# 绘制饼图并获取返回值
plt.figure(figsize=(8,6))
wedges, texts, autotexts = plt.pie(
        x=[21, 35, 19, 20], 
        labels=['类别A''类别B''类别C''类别D'],
        autopct='%1.2f%%',
        colors=['#FF9999','#66B2FF','#99FF99','#FFCC99']
       )

# 通过返回值对象进行精细定制
# 1. 设置“类别B”扇形的边框为红色并加粗
wedges[1].set_edgecolor('red')
wedges[1].set_linewidth(2)
# 2. 将“类别B”扇形的百分比文本的颜色设置为红色并加粗
autotexts[1].set_color('red')
autotexts[1].set_fontsize(18)
autotexts[1].set_fontweight('bold')
# 3. 将“类别B”标签的字体设置为红色并加粗
texts[1].set_fontsize(18)
texts[1].set_color('red')
texts[1].set_fontweight('bold')

plt.title('通过返回值对象进行精细定制', fontsize=14)
plt.show()

可视化结果如下图所示:

02

使用示例


  • 示例1:添加图例

使用默认的legend()函数为饼图添加图例时,图例和圆饼图会重叠在一起。这是因为若用轴(axes)的模式看饼图,整个饼图就是一个图表的全部,因此使用legend()函数添加的图例和饼图会重叠。

如果要避免图例与饼图重叠,在legend()函数内需使用bbox_to_anchor()参数,用于精确调整图例(或其他元素)位置,它的作用是将图例 “锚定” 到指定坐标位置,从而实现更灵活的布局控制。

# 准备数据
values = [260, 320, 280, 450]  # 数据
labels = ['类别A''类别B''类别C''类别D']  # 标签

# 自定义图例标签(可以包含额外信息)
legend_labels = [f'{label}: {value}'for label, value in zip(labels, values)]

# 绘制饼图,先不设置labels(避免与图例中的标签重复)
wedges, texts, autotexts = plt.pie(
    x=values,
    autopct='%1.1f%%'
)

# 添加图例
plt.legend(
    wedges,  # 将图例与饼图的扇形对象关联,确保颜色对应
    legend_labels,  # 使用自定义的图例文本
    title='图例',
    loc='center left',  # 图例在图表中的基准位置(左侧中间)

    # 调整图例位置
    # 将图例的基准点锚定到 (1, 0.5) 位置(即图表右侧中间位置)
    bbox_to_anchor=(1, 0, 0.5, 1)  
)

plt.title('为饼图添加图例', fontsize=14, pad=10)
plt.axis('equal')
plt.show()

可视化结果如下图所示:


  • 示例2:绘制环形饼图

使用 pie() 函数绘制环形饼图(也称为 “甜甜圈图”)的核心原理是在普通饼图的基础上,通过设置扇形的内半径不为 0,形成中间空心的效果。

普通饼图的扇形(Wedge 对象)默认内半径为 0,外半径由 radius 参数控制(默认值为 1),因此呈现为实心的圆形切片。

环形饼图的核心是让扇形拥有内半径(width),即扇形是一个 “圆环的切片” 而非 “实心圆的切片”。这可以通过 pie() 函数的 wedgeprops 参数实现,该参数接受一个字典,用于设置扇形的样式,其中 width 键专门控制内半径比例。width 的值为 0~1 之间的浮点数,表示环形的 “厚度” 占外半径的比例。例如 width=0.7 表示环形的外半径为 radius(默认 1),内半径为 radius × (1-0.7) = 0.3,形成中间空心的效果。

import matplotlib.pyplot as plt

# 数据准备
sizes = [15, 30, 45, 10]
labels = ['A''B''C''D']

plt.figure(figsize=(8, 8))

plt.pie(sizes, 
        labels=labels, 
        autopct='%1.1f%%',
        pctdistance=0.8,  # 百分比文本与圆心的距离(相对半径的比例)
        wedgeprops=dict(width=0.4, edgecolor='k')  # width控制环的厚度
)  

plt.title('环形饼图')
plt.show()

可视化结果如下图所示:


  • 示例3:绘制多级饼图

使用 pie() 函数绘制多级饼图(也称为嵌套饼图)的核心原理是在同一坐标系中绘制多个半径不同的饼图,通过内外层半径差异形成嵌套结构,从而展示数据的层级关系。实现思路如下:

  • 调用多次 plt.pie() 函数,每次绘制一层饼图
  • 通过 radius 参数控制各层半径(内层半径 < 外层半径)
  • 用 wedgeprops 参数的 width 控制每层的厚度(类似环形饼图)
  • 确保各层数据逻辑对应(如内层数据总和应等于外层某一分类的值)
# 外层数据(一级分类)
outer_values = [100, 150, 200]
outer_labels = ["部门1""部门2""部门3"]

# 内层数据
inner_values = [30, 50, 20]
inner_labels = ["本科人数""硕士人数""博士人数"]

# 绘制外层饼图(环形)
plt.pie(
    outer_values,
    labels=outer_labels,
    radius=1,  # 外层半径
    labeldistance=0.8 ,
    wedgeprops={"width": 0.3, "edgecolor""white"}  # 厚度0.3,白色边框分隔
)

# 绘制内层饼图(仅展示产品A的细分)
plt.pie(
    inner_values,
    labels=inner_labels,
    radius=1 - 0.3,  # 内层半径 = 外层半径 - 外层厚度
    wedgeprops={"width": 0.4, "edgecolor""white"},  # 内层厚度0.2
    labeldistance=0.5
)

plt.axis("equal")  # 保证正圆形
plt.title("多级饼图")
plt.show()
可视化结果如下图所示:
  • 示例4:建立饼图间的关联

要在两个饼图之间建立视觉联系,可以使用 Matplotlib 的 ConnectionPatch 函数。该函数能创建一条连线(直线或曲线),连接两个图表中的指定位置,常用于强调数据间的关联关系。

# 导入ConnectionPatch模块,用于在两个子图之间创建连接线
from matplotlib.patches import ConnectionPatch

# 创建画布和子图(1行2列)
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 5))
fig.subplots_adjust()

# 左侧饼图数据
left_values = [100, 150, 200,300]
left_labels = ["部门1""部门2""部门3""部门4"]
# 右侧饼图数据
right_values = [450, 200, 100]
right_labels = ["本科人数""硕士人数""博士人数"]
# 在左侧子图ax1中绘制饼图
ax1.pie(left_values, autopct='%1.1f%%', startangle=20, labels=left_labels)
ax1.set_title("某公司各部门人数", color='b')
# 在右侧子图ax2中绘制饼图
ax2.pie(right_values, autopct='%1.1f%%', startangle=70, labels=right_labels, radius=0.7)
ax2.set_title("学历比例调查表", color='b')

# 创建上方连接线:连接左侧子图(0,1)位置和右侧子图(0,0.7)位置
# xyA/xyB:连接线两端在各自子图中的坐标(数据坐标系)
# coordsA/coordsB:指定使用数据坐标系
# axesA/axesB:指定连接线所属的两个子图
con_a = ConnectionPatch(xyA=(0, 1), xyB=(0, 0.7), coordsA=ax1.transData, coordsB=ax2.transData, axesA=ax1, axesB=ax2)
# 创建下方连接线:连接左侧子图(0,-1)位置和右侧子图(0,-0.7)位置
con_b = ConnectionPatch(xyA=(0, -1), xyB=(0, -0.7), coordsA=ax1.transData, coordsB=ax2.transData, axesA=ax1, axesB=ax2)

# 将两条连接线添加到右侧子图中(使连接线显示在图表上)
for con in [con_a, con_b]:
    ax2.add_artist(con)
    
plt.show()

可视化结果如下图所示:



更多内容可以前往官网查看

https://matplotlib.org/stable/


本篇文章来源于微信公众号: 码农设计师

RELATED ARTICLES

欢迎留下您的宝贵建议

Please enter your comment!
Please enter your name here

- Advertisment -

Most Popular

Recent Comments