0. 概述
饼图会出现在很多需要呈现各部分在整体中比重的场合,而且会有一系列的变种,这里把常见的一些饼图及绘制方式整理一下。
当然这里不可能覆盖所有的场景,不过通过对一些参数的演示和讲解,相信大家也可以绘制出符合自己需求的饼图。
1. 基本绘制方法
使用Matplotlib的pie方法可以很方便的绘制饼图,其底层的实现应该是使用到了matplotlib.patches下的Wedge对象。
一个命令就可以调用该函数,然后绘制图形,以下几行的代码就可以绘制并显示一个饼图:
fig,ax=plt.subplots()
values=rd.randint(20,60,5) #五个介于20到60之间的随机数
ax.pie(values)
plt.show()
运行效果如下:
2. 其他元素
当然,上面的例子还缺少不少元素,例如每一部分所代表的含义,以及百分比分别代表的是什么并不清晰,可以在pie中添加一些参数,例如:
import numpy as np
import matplotlib.pyplot as plt
import numpy.random as rd
from matplotlib import cm
fig,ax=plt.subplots()
values=rd.randint(20,60,5) #五个介于20到60之间的随机数
labels=['A','B','C','D','E'] #标签
colors=cm.rainbow(np.linspace(0,1,len(values))) #颜色
#指定labels和colors参数,并设置autopct参数,以百分比形式显示饼图的值
ax.pie(values,labels=labels,colors=colors,autopct='%1.1f%%')
plt.show()
运行效果如下:
另外,可以通过指定labeldistance和pctdistance调节显示标签到圆心的相对距离。
3. 阴影和分离
通过shadow和explode参数还可以指定阴影和分离效果,以突出重点,例如:
import numpy as np
import matplotlib.pyplot as plt
import numpy.random as rd
from matplotlib import cm
fig,ax=plt.subplots()
values=rd.randint(20,60,5) #五个介于20到60之间的随机数
labels=['A','B','C','D','E'] #标签
colors=cm.rainbow(np.linspace(0,1,len(values))) #颜色
#指定labels和colors参数,并设置autopct参数,以百分比形式显示饼图的值
explode=[0.1,0,0.2,0,0] #突出显示的部分
ax.pie(values,labels=labels,colors=colors,autopct='%1.1f%%',
explode=explode,shadow=True)
plt.show()
参数Shadow决定是否带阴影,而explode列表,确定了对应份在径向上的分离程度,上面的代码中,A对应的是0.1,而C对应的是0.2,显然C比A更加远离圆心。效果如下:
4. 起始角度和方向
前面的几个图我们可以看到起始角度是从0度开始,并且采用逆时针方式进行绘制的,起始也可以通过参数startangle和counterclock(逆时针),指定起始角度和旋转方向。需要注意的是,起始角度以度为单位,因此180表示半圈,此外,无论绘制饼图是顺时针还是逆时针,起始角度总是按逆时针为正,顺时针为负。示例代码及效果如下:
import numpy as np
import matplotlib.pyplot as plt
import numpy.random as rd
from matplotlib import cm
fig,ax=plt.subplots()
values=rd.randint(20,60,5) #五个介于20到60之间的随机数
labels=['A','B','C','D','E'] #标签
colors=cm.rainbow(np.linspace(0,1,len(values))) #颜色
ax.pie(values,labels=labels,colors=colors,autopct='%1.1f%%',
startangle=90,counterclock=False)
plt.show()
5. 环形饼图
有时候需要绘制环形饼图的样式,这个可以通过wedgeprops参数来配置:
# 环形饼图
import matplotlib.pyplot as plt
# 数据
sizes = [30, 25, 20, 15, 10]
labels = ['A', 'B', 'C', 'D', 'E']
colors = ['#ff9999','#66b3ff','#99ff99','#ffcc99','#c2c2f0']
r=1
k=0.382
# 若想让饼图为满圆,则k=1
plt.pie(sizes,
labels=labels,
radius=r,
colors=colors,
startangle=90,
autopct='%.2f%%',
pctdistance=0.8,
wedgeprops=dict(width=r*k,edgecolor='w'))
plt.legend(loc='upper right', bbox_to_anchor=(r,r))
# Equal aspect ratio ensures that pie is drawn as a circle.
plt.axis('equal')
plt.title('circular pie chart')
plt.show()
效果如下:
6. 嵌套环形饼图
嵌套环形饼图起始和环形饼图完全一样,就是画两遍饼图,唯一需要注意的是两次饼图的内径和外径,示例代码如下(来自matplotlib官网):
import numpy as np
import matplotlib.pyplot as plt
import numpy.random as rd
from matplotlib import cm
fig, ax = plt.subplots()
size = 0.3
vals = np.array([[60., 32.], [37., 40.], [29., 10.]])
tab20c = plt.color_sequences["tab20c"]
outer_colors = [tab20c[i] for i in [0, 4, 8]]
inner_colors = [tab20c[i] for i in [1, 2, 5, 6, 9, 10]]
ax.pie(vals.sum(axis=1), radius=1, colors=outer_colors,
wedgeprops=dict(width=size, edgecolor='w'))
ax.pie(vals.flatten(), radius=1-size, colors=inner_colors,
wedgeprops=dict(width=size, edgecolor='w'))
ax.set(aspect="equal", title='Pie plot with `ax.pie`')
plt.show()
效果如下:
7. 带标注饼图
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.cm as cm
labels = ['Apple', 'Banana', 'Orange','Mango','Grapes','watermelon']
values=np.random.randint(20,100,len(labels))
colors = cm.Spectral(np.linspace(0, 1, len(labels)))
fig, ax = plt.subplots()
wedges, _ = ax.pie(values,colors=colors, startangle=90)
# add annotations
kw = dict(arrowprops=dict(arrowstyle="-|>", color='blue'),
bbox=dict(boxstyle="round", fc="darkgray", ec=None), zorder=0, va="center")
total=sum(values)
pct=[100*x / total for x in values]
for i, p in enumerate(wedges):
ang = (p.theta2 - p.theta1)/2. + p.theta1
kw['arrowprops'].update({'connectionstyle': f'angle,angleA=0,angleB={ang}'})
y = np.sin(np.deg2rad(ang))
x = np.cos(np.deg2rad(ang))
horizontalalignment = {-1: "right", 1: "left"}[int(np.sign(x))]
connectionstyle = "angle,angleA=0,angleB={}".format(ang)
ax.annotate(f'{pct[i]:.1f}% {labels[i]}', xy=(x, y), color='white',xytext=(1.3*np.sign(x), 1.2*y),
horizontalalignment=horizontalalignment, **kw)
ax.set_xlim(-1.5, 1.5)
ax.set_ylim(-1.5, 1.5)
ax.set_aspect('equal')
ax.set_title('Pie Chart with Annotations')
plt.show()
效果如下:
8. 配置不同填充
前面介绍的那么多,每个扇区的样式都是纯色的,也可以通过hatch参数指定不一样的填充形式,例如:
import numpy as np
import matplotlib.pyplot as plt
import numpy.random as rd
from matplotlib import cm
fig,ax=plt.subplots()
values=rd.randint(20,60,5) #五个介于20到60之间的随机数
labels=['A','B','C','D','E'] #标签
colors=cm.rainbow(np.linspace(0,1,len(values))) #颜色
hatches = ['//', '\\\\', '||', '--', '++'] # 条纹样式
ax.pie(values,labels=labels,colors=colors,autopct='%1.1f%%',hatch=hatches)
plt.show()
效果如下: