Python绘制饼图(附带实例)
饼图(Pie Chart)用于展示各类别在整体中的比例关系。它以圆形为基础,将整体分成多个扇形,每个扇形的角度大小表示该类别在总体中的比例或占比。
饼图的优点是可以直观地展示各类别在整体中的相对比例,常用于表示不同类别的市场份额、调查结果中的频数分布等。在使用饼图时,应选择合适的数据和合适的类别数量,以确保图表的可读性和准确传达数据。在使用饼图时,建议明确标记饼图每个部分的百分比或数字。
【实例 1】饼图绘制示例 1。输入如下代码:
输出的结果如下图所示:

图 1 饼图1
【实例 2】饼图绘制示例 2。输入如下代码:
输出的结果如下图所示:

图 2 饼图2
【实例 3】饼图绘制示例3。输入如下代码:
饼图显示了 Approve、Disapprove 和 Undecided 的比例,而柱状图显示了不同年龄段的比例。通过 ConnectionPatch 类在两个子图之间绘制连接线,将柱状图的柱子与饼图的楔形图连接起来,以突出不同年龄段在 Approve 类别中的比例。
输出的结果如下图所示:

图 3 饼图3
【实例 4】绘制环形饼图,并对其进行标记。输入如下代码:
输出的结果如下图所示:

图 4 添加标记的环形饼图
饼图的优点是可以直观地展示各类别在整体中的相对比例,常用于表示不同类别的市场份额、调查结果中的频数分布等。在使用饼图时,应选择合适的数据和合适的类别数量,以确保图表的可读性和准确传达数据。在使用饼图时,建议明确标记饼图每个部分的百分比或数字。
【实例 1】饼图绘制示例 1。输入如下代码:
import pandas as pd import matplotlib.pyplot as plt # 准备数据 df_raw = pd.read_csv("D:/DingJB/PyData/mpg_ggplot2.csv") # 读取数据 # 根据车辆类型(class)对数据进行分组,并计算每个类型的数量 df = df_raw.groupby('class').size() df.plot(kind='pie', subplots=True, figsize=(5, 5)) # 使用 Pandas 绘制饼图 # 设置标题和坐标轴标签 plt.title("Pie Chart of Vehicle Class-Bad") plt.ylabel("") plt.show()上述代码使用 Pandas 从 CSV 文件中读取数据,然后根据车辆类型对数据进行分组,并计算每个类型的数量。接着使用 Pandas 绘制了一个饼图,用于展示每个车辆类型所占的比例。最后,添加了标题和坐标轴标签,使图表更具可读性。
输出的结果如下图所示:

图 1 饼图1
【实例 2】饼图绘制示例 2。输入如下代码:
import pandas as pd import matplotlib.pyplot as plt import numpy as np # 从 csv 文件中读取数据 df_raw = pd.read_csv("D:/DingJB/PyData/mpg_ggplot2.csv") # 准备数据 # 根据车辆类型(class)对数据进行分组,并计算每个类型的数量 df = df_raw.groupby('class').size().reset_index(name='counts') # 绘制图形 # 创建图形和轴对象,设置图形大小和等轴比例 fig, ax = plt.subplots(figsize=(8, 6), subplot_kw=dict(aspect="equal")) # 提取数据和类别 data = df['counts'] categories = df['class'] explode = [0, 0, 0, 0, 0, 0, 1, 0] # 设置饼图的爆炸程度 # 定义一个函数,用于在饼图上显示百分比和绝对值 def func(pct, allvals): absolute = int(pct/100. * np.sum(allvals)) return "{:.1f}% ({:d})".format(pct, absolute) # 绘制饼图 wedges, texts, autotexts = ax.pie(data, autopct=lambda pct: func(pct, data), textprops=dict(color="w"), colors=plt.cm.Dark2.colors, startangle=140, explode=explode) # 图形修饰 ax.legend(wedges, categories, title="Vehicle Class", loc="center left", bbox_to_anchor=(1, 0, 0.5, 1)) # 添加图例 plt.setp(autotexts, size=10, weight=700) # 设置自动文本的大小和字重 ax.set_title("Class of Vehicles: Pie Chart") # 设置图形标题 plt.show()上述代码首先从 CSV 文件中读取数据,然后根据车辆类型(class)对数据进行分组,并计算每个类型的数量。接着使用 Matplotlib 绘制了一个饼图,用于展示每个车辆类型所占的比例,并在饼图上显示百分比和绝对值。最后,添加了图例和图形标题,使图表更具可读性。
输出的结果如下图所示:

图 2 饼图2
【实例 3】饼图绘制示例3。输入如下代码:
import matplotlib.pyplot as plt import numpy as np from matplotlib.patches import ConnectionPatch # 创建图形和轴对象 fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(9, 5)) fig.subplots_adjust(wspace=0) # 饼图参数 overall_ratios = [.27, .56, .17] labels = ['Approve', 'Disapprove', 'Undecided'] explode = [0, 1, 0] angle = -180 * overall_ratios[0] # 旋转角度使得第 1 个楔形图被 X 轴分隔 wedges, *_ = ax1.pie(overall_ratios, autopct='%1.1f%%', startangle=angle, labels=labels, explode=explode) # 柱状图参数 age_ratios = [.33, .54, .07, .06] age_labels = ['Under 35', '35-49', '50-65', 'Over 65'] bottom = 1 width = .2 # 从顶部开始添加,以匹配图例 for j, (height, label) in enumerate(reversed([(*zip(age_ratios, age_labels))])): bottom -= height bc = ax2.bar(0, height, width, bottom=bottom, color='C0', label=label, alpha=0.1 + 0.25 * j) ax2.bar_label(bc, labels=[f"{height:.0f}%"], label_type='center') # 设置柱状图的标题、图例和坐标轴 ax2.set_title('Age of approvers') ax2.legend() ax2.axis('off') ax2.set_xlim(-2.5 * width, 2.5 * width) # 使用 ConnectionPatch 在两个子图之间绘制连接线 theta1, theta2 = wedges[0].theta1, wedges[0].theta2 center, r = wedges[0].center, wedges[0].r bar_height = sum(age_ratios) # 绘制顶部连接线 x = r * np.cos(np.pi / 180 * theta2) + center[0] y = r * np.sin(np.pi / 180 * theta2) + center[1] con = ConnectionPatch(xyA=(-0.5 * width, bar_height), coordsA=ax2.transData, xyB=(x, y), coordsB=ax1.transData) con.set_color([0, 0, 0]) con.set_linewidth(2) ax2.add_artist(con) # 绘制底部连接线 x = r * np.cos(np.pi / 180 * theta1) + center[0] y = r * np.sin(np.pi / 180 * theta1) + center[1] con = ConnectionPatch(xyA=(-0.5 * width, 0), coordsA=ax2.transData, xyB=(x, y), coordsB=ax1.transData) con.set_color([0, 0, 0]) con.set_linewidth(2) ax2.add_artist(con) plt.show()上述代码创建了一个具有两个子图的图形,一个子图是饼图,另一个是柱状图。
饼图显示了 Approve、Disapprove 和 Undecided 的比例,而柱状图显示了不同年龄段的比例。通过 ConnectionPatch 类在两个子图之间绘制连接线,将柱状图的柱子与饼图的楔形图连接起来,以突出不同年龄段在 Approve 类别中的比例。
输出的结果如下图所示:

图 3 饼图3
【实例 4】绘制环形饼图,并对其进行标记。输入如下代码:
import matplotlib.pyplot as plt import numpy as np # 创建一个大小为 (6,4) 的图,并设置子图属性为“等比例” fig, ax = plt.subplots(figsize=(6, 4), subplot_kw=dict(aspect="equal")) # 配方和数据 recipe = ["225 g flour", "90 g sugar", "1 egg", "60 g butter", "100 ml milk", "1/2 package of yeast"] data = [225, 90, 50, 60, 100, 5] # 绘制饼图 wedges, texts = ax.pie(data, wedgeprops=dict(width=0.5), startangle=-40) # 注释框的属性 bbox_props = dict(boxstyle="square,pad=0.3", fc="w", ec="k", lw=0.72) kw = dict(arrowprops=dict(arrowstyle="-"), bbox=bbox_props, zorder=0, va="center") # 遍历每个扇形并添加注释 for i, p in enumerate(wedges): # 计算注释的位置 ang = (p.theta2 - p.theta1) / 2. + p.theta1 y = np.sin(np.deg2rad(ang)) x = np.cos(np.deg2rad(ang)) # 水平对齐方式根据 x 坐标的正负确定 horizontalalignment = {-1: "right", 1: "left"}[int(np.sign(x))] # 设置连接线的样式 connectionstyle = f"angle,angleA=0,angleB={ang}" kw["arrowprops"].update({"connectionstyle": connectionstyle}) # 添加注释 ax.annotate(recipe[i], xy=(x, y), xytext=(1.35*np.sign(x), 1.4*y), horizontalalignment=horizontalalignment, **kw) ax.set_title("Matplotlib bakery: A donut") # 设置标题 plt.show()上述代码利用 Matplotlib 创建了一个饼图,展示了烘焙食谱中不同成分的比例,通过注释标明每个扇形对应的成分及其比例,并在每个扇形中心添加了成分名称的注释,使得图形更具可读性。
输出的结果如下图所示:

图 4 添加标记的环形饼图