前言

饼图是一种常见的数据可视化方式,因为长得像烧饼,故名曰饼图,英文名pie chart, 常用来表示某一事物内部构成大小及占比,比如一杯鲜奶的水分:87.5%,脂肪:3.5-%,蛋白质:2.8%,乳糖:4.6%,无机盐:0.7%等,这时候用一个像烧饼的东西来刻画鲜奶各部分的含量,如下图
python画饼图_Python教程
一个事物内部结构也许比较清楚,用excel也很容易画出来,但是多个对象的内部结构要一起展示,这时候excel显得有些吃力,这一篇主要讲多对象饼图的绘画。

思路

python画图主要还是matplotlib模块,在matplotlib中,整个图像为一个Figure对象。在Figure对象像切豆腐一样,切成多个axes对象。每个axes对象都是一个拥有自己坐标系统的绘图区域。画子图就需要plt.subplots()函数,该函数返回一个包含figure和axes对象的元组,其中figure用来标识子图对象,axes标识子图对象的位置。画多个饼图就可以,一个子图位置上画一张饼图,然后拼成饼图矩阵。实际操作中反过来的,首先建立饼图矩阵坑,然后每一个坑用一个饼图去填坑。

数据预览与结果预览

现在有如下数据
python画饼图_Python教程_02
共4各对象,每个对象有4类数据,也就是要为每个饼切4刀,现在想要为每个板块画一个饼图来刻画各类产业占比,且标识每个饼图是哪个板块,每个板块里的产业占比和标签。
结果预览如下
python画饼图_Python教程_03

代码
import pandas as pd #导入数据分析模块
import matplotlib.pyplot as plt #导入绘图模块
plt.rcParams['font.sans-serif']='SimHei'
data=pd.read_excel("饼图数据.xlsx",index_col='城市') #读取数据
row_sum=data.sum(axis=1) #按行求和
partion_data=data.div(row_sum,axis=0) #计算行百分比
labels_="知识密集型","技术密集型","资源密集型","劳动力密集型" #设置标签
colors_=["aliceblue","antiquewhite","aqua","aquamarine"] #设置饼图配色
fig,ax=plt.subplots(nrows=2, ncols=2) #2x2的图形矩阵
axes = ax.flatten() #子图展平
axes[0].pie(partion_data.iloc[0,:],autopct='%1.1f%%',labels=labels_,colors=colors_, explode=(0, 0, 0, 0.1),shadow=True) #第一个饼图
axes[0].set_title("杭州2018") ##设置第一个子图标题

axes[1].pie(partion_data.iloc[1,:],autopct='%1.1f%%',labels=labels_,colors=colors_, explode=(0.1, 0, 0, 0),shadow=True) #第二个饼图
axes[1].set_title("杭州2019") #设置第二个子图标题

axes[2].pie(partion_data.iloc[2,:],autopct='%1.1f%%',labels=labels_,colors=colors_,explode=(0,0.1,0,0),shadow=True) #第三个饼图
axes[2].set_title("广州2018")

axes[3].pie(partion_data.iloc[2,:],autopct='%1.1f%%',labels=labels_,colors=colors_,explode=(0,0,0.1,0),shadow=True) #第四个子图
axes[3].set_title("广州2019")

plt.savefig("饼图.png",dpi=200) #设置像素保存
plt.show() #显示图片
改进思路

为了画四个饼图,用了四个长长的语句,这显然与代码的简洁性相违背,且上下两行图太紧凑了,使得下行子图标题与上行子图的页标签有重合之势,于是想定义一个画图函数,然后循环对各部分数据进行调用即可,并对子图间间隔进行微调。依循这个思路,改进代码如下

改进代码
import pandas as pd #导入数据分析模块
import matplotlib.pyplot as plt #导入绘图模块
plt.rcParams['font.sans-serif']='SimHei'
data=pd.read_excel("饼图数据.xlsx",index_col='板块') #读取数据
row_sum=data.sum(axis=1) #按行求和
partion_data=data.div(row_sum,axis=0) #计算行百分比
rows,cols=data.shape #数据尺寸
fig,ax=plt.subplots(nrows=2,ncols=2,figsize=(6, 6)) #建立饼图坑
axes=ax.flatten() #将坑位展平
labels_="知识密集型","技术密集型","资源密集型","劳动力密集型" #设置标签
colors_=["aliceblue","antiquewhite","aqua","aquamarine"] #设置饼图配色
for row in range(rows):
    axes[row].pie(partion_data.iloc[row,:],autopct='%1.1f%%',labels=labels_,colors=colors_, explode=(0.05, 0, 0, 0),shadow=True) #绘制子饼图
    axes[row].set_title(data.index[row]) #设置标题
    plt.subplots_adjust(left=None, bottom=None, right=None, top=None,wspace=0.7, hspace=0.3) #调整子图间距
    plt.savefig("pie.png",dpi=200) #保存图片

使用subplots_adjust来调整子图的间距,其中的wspace是子图之间的左右间距,hspace是子图的上下间距,

import pandas as pd #导入数据分析模块
import matplotlib.pyplot as plt #导入绘图模块
plt.rcParams['font.sans-serif']='SimHei'
data=pd.read_excel("饼图数据.xlsx",index_col='板块') #读取数据
row_sum=data.sum(axis=1) #按行求和
partion_data=data.div(row_sum,axis=0) #计算行百分比
rows,cols=data.shape #数据尺寸
fig,ax=plt.subplots(nrows=2,ncols=2,figsize=(6, 6)) #建立饼图坑
axes=ax.flatten() #将坑位展平
labels_="知识密集型","技术密集型","资源密集型","劳动力密集型" #设置标签
colors_=["aliceblue","antiquewhite","aqua","aquamarine"] #设置饼图配色
for row in range(rows):
    explode=[0, 0, 0, 0] #初始化突出位置
    explode[row]=0.05 #新的突出切片
    axes[row].pie(partion_data.iloc[row,:],autopct='%1.1f%%',labels=labels_,colors=colors_, explode=explode,shadow=True) #绘制子饼图
    axes[row].set_title(data.index[row]) #设置标题
    plt.subplots_adjust(left=None, bottom=None, right=None, top=None,wspace=0.5, hspace=0.2) #调整子图间距
    plt.savefig("pie.png",dpi=200) #保存图片

运行效果图
python画饼图_Python教程_04

代码解读

后面的饼图好看多了,大部分都给出了注释
python画饼图_Python教程_05