第五章 Python 数据可视化
1、Matplotlib 基础
1.1 Matplotlib 库介绍
Matplotlib 是 Python 最著名的绘图库,它提供了一整套和 Matlab 相似的命令 API,十分适合交互式地进行制图。而且也可以方便地将它作为绘图控件,嵌入 GUI 应用程序中。
Matplotlib 库由各种可视化类构成,内部结构复杂。
Matplotlib.pyplot 是绘制各类可视化图形的命令字库,相当于快捷方式。
Matplotlib 文档相当完备,并且 Gallery 页面中有上百幅缩略图,打开之后都有源代码。因此如果你需要绘制某种类型的图,只需要在这个页面中浏览、复制、 粘贴一下,基本上通过修改数据和设置都能搞定。
1.1.1 Matplotlib 库效果
https://matplotlib.org/gallery/index.html
1.1.2 Matplotlib 库 Gallery 示例
import numpy as np
import matplotlib.pyplot as plt
N = 5
menMeans = (20, 35, 30, 35, 27)
womenMeans = (25, 32, 34, 20, 25)
menStd = (2, 3, 4, 1, 2)
womenStd = (3, 5, 2, 3, 3)
ind = np.arange(N) # the x locations for the groups width = 0.35 # the width of the bars
p1 = plt.bar(ind, menMeans, width, yerr=menStd)
p2 = plt.bar(ind, womenMeans, width,
bottom=menMeans, yerr=womenStd)
plt.ylabel('Scores')
plt.title('Scores by group and gender')
plt.xticks(ind, ('G1', 'G2', 'G3', 'G4', 'G5'))
plt.yticks(np.arange(0, 81, 10))
plt.legend((p1[0], p2[0]), ('Men', 'Women'))
plt.show()
或者新版本代码
import numpy as np
import matplotlib.pyplot as plt
labels = ['G1', 'G2', 'G3', 'G4', 'G5']
men_means = [20, 35, 30, 35, 27]
women_means = [25, 32, 34, 20, 25]
men_std = [2, 3, 4, 1, 2]
women_std = [3, 5, 2, 3, 3]
width = 0.35 # the width of the bars: can also be len(x) sequence
fig, ax = plt.subplots()
ax.bar(labels, men_means, width, yerr=men_std, label='Men')
ax.bar(labels, women_means, width, yerr=women_std, bottom=men_means,
label='Women')
ax.set_ylabel('Scores')
ax.set_title('Scores by group and gender')
ax.legend()
plt.show()
1.2 Matplotlib 快速绘图
1.2.1 快速绘图
- matplotlib 中的快速绘图的函数库可以通过如下语句载入:
import matplotlib.pyplot as plt
- 接下来调用 figure 创建一个绘图对象,并且使它成为当前的绘图对象:
plt.figure(figsize=(8,4))
通过 figsize 参数可以指定绘图对象的宽度和高度,单位为英寸; dpi 参数指定绘图对象的分辨率,即每英寸多少个像素,缺省值为 80 。
也可以不创建绘图对象直接调用接下来的 plot 函数直接绘图,matplotlib 会自动创建一个绘图对象。
在使用 Jupyter Notebook 环境绘图时,需要先运行 Jupyter Notebook 的魔术命令
%matplotlib inline
。这条命令的作用是将 Matplotlib 绘制的图形嵌入在当前页面中。而在桌面环境中绘图时,不需要添加此命令,而是在全部绘图代码之后追加plt.show()
。
%matplotlib inline
如果需要同时绘制多幅图表的话,可以是给 figure 传递一个整数参数指定图标的序号,如果所指定序号的绘图对象已经存在的话,将不创建新的对象,而只是让它成为当前绘图对象。
plot 函数的调用方式很灵活,使用关键字参数指定各种属性:
➢ label: 给所绘制的曲线一个名字 , 此名字在图示 (legend) 中显示 。 只要在字符串前后添加 “$” 符号 , matplotlib 就会使用其内嵌的latex 引擎绘制的数学公式;
➢ color: 指定曲线的颜色;
➢ linewidth: 指定曲线的宽度;
➢ 参数b --
指定曲线的颜色和线型可通过一系列函数设置绘图对象的各个属性:
➢ xlabel/ylabel:设置 X 轴/Y轴 的文字
➢ title:设置图表的标题
➢ ylim:设置Y轴的范围
➢ legend:图例图示
➢ plt.show ():显示出创建的所有绘图对象
plt.xlabel("Time(s)")
plt.ylabel("Volt")
plt.title("PyPlot First Example") plt.ylim(-1.2,1.2)
plt.legend()
- 可以调用 plt. savefig () 将当前的 Figure 对象保存成图像文件 , 图像格式由图像文件的扩展名决定
plt.savefig(“test.png”,dpi=120)
1.2.2 快速绘图示例
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 10, 500)
y = np.sin(x)
z = np.cos(x**2)
plt.figure(figsize=(8,6))
plt.plot(x,y,label="$sin(x)$",color="red",linewidth=2)
plt.plot(x,z,"b--",label="$cos(x^2)$")
plt.xlabel("Time(s)")
plt.ylabel("Volt")
plt.title("PyPlot First Example")
plt.ylim(-1.2,1.2)
plt.legend()
plt.show()
#plt.savefig("test.png",dpi=120)
1.3 Matplotlib 库使用初探
- pyplot 的基础图标函数如下
函数 | 说明 |
---|---|
plt.plot(x,y,fmt,…) | 绘制一个坐标图 |
plt.boxplot(data, notch, position) | 绘制一个箱形图 |
plt.bar(left, height, width, bottom) | 绘制一个柱状图 |
plt.barh(width, bottom, left, height) | 绘制一个横向条形图 |
plt.polar(theta, r) | 绘制极坐标图 |
plt.pie(data, explode) | 绘制饼状图 |
plt.psd(x, NFFT=256, pad_to, Fs) | 绘制功率谱密度图 |
plt.cohere(x, y, NFFT=256, Fs) | 绘制X-Y的相关性函数 |
plt.scatter(x, y) | 绘制散点图,其中,x和y长度相同 |
plt.step(x, y, where) | 绘制步阶图 |
plt.hist(x, bins, normed) | 绘制直方图 |
plt.contour(X, Y, Z, N) | 绘制等值图 |
plt.vlines() | 绘制垂直图 |
plt.stem(x, y, linefmt, markerfmt) | 绘制柴火图 |
plt.plot_date() | 绘制数据日期 |
pyplot 的绘图区域
1)可以用子图来将图样(plot)放在均匀的坐标网格中。
2)plt.subplot(nrows, ncols, plot_number)。
3)用 subplot 函数的时候,需要指明网格的行列数量,以及你希望将图样放在哪一个网格区域中。pyplot的绘图区域示例
import matplotlib.pyplot as plt
plt.subplot(2,1,1)
plt.xticks([]), plt.yticks([])
plt.text(0.5,0.5,
'subplot(2,1,1)',ha='center',va='center',size=24,alpha=.5)
plt.subplot(2,1,2)
plt.xticks([]), plt.yticks([])
plt.text(0.5,0.5,
'subplot(2,1,2)',ha='center',va='center',size=24,alpha=.5)
# plt.savefig('./medias/figures/subplot-horizontal.png', dpi=64)
plt.show()
import matplotlib.pyplot as plt
plt.subplot(1,2,1)
plt.xticks([]), plt.yticks([])
plt.text(0.5,0.5,
'subplot(1,2,1)',ha='center',va='center',size=24,alpha=.5)
plt.subplot(1,2,2)
plt.xticks([]), plt.yticks([])
plt.text(0.5,0.5,
'subplot(1,2,2)',ha='center',va='center',size=24,alpha=.5)
# plt.savefig('./medias/figures/subplot-horizontal.png', dpi=64)
plt.show()
import matplotlib.pyplot as plt
plt.subplot(2,2,1)
plt.xticks([]), plt.yticks([])
plt.text(0.5,0.5,
'subplot(2,2,1)',ha='center',va='center',size=24,alpha=.5)
plt.subplot(2,2,2)
plt.xticks([]), plt.yticks([])
plt.text(0.5,0.5,
'subplot(2,2,2)',ha='center',va='center',size=24,alpha=.5)
plt.subplot(2,2,3)
plt.xticks([]), plt.yticks([])
plt.text(0.5,0.5,
'subplot(2,2,3)',ha='center',va='center',size=24,alpha=.5)
plt.subplot(2,2,4)
plt.xticks([]), plt.yticks([])
plt.text(0.5,0.5,
'subplot(2,2,4)',ha='center',va='center',size=24,alpha=.5)
# plt.savefig('./medias/figures/subplot-horizontal.png', dpi=64)
plt.show()
2、折线图、散点图实战
2.1 折线图实战
2.1.1 折线图
- 折线图通常用来表示数据随时间或有序类别变化的趋势。
- 最简单的折线图示例。
import matplotlib.pyplot as plt
data=[1,2,3,4,5,4,2,4,6,7] # 随意创建的数据
plt.plot(data) # 引用matplotlib库中的pyplot模块绘图
plt.show()
折线图通常用来表示数据随时间或有序类别变化的趋势。
plot() 函数的第一个参数表示横坐标数据
第二个参数表示纵坐标数据
第三个参数表示颜色、线型和标记样式
颜色常用的值有(r/g/b/c/m/y/k/w)
线型常用的值有(-/–/:/-.)
标记样式常用的值有(/medias/,/o/v/^/s/*/D/d/x/</>/h/H/1/2/3/4/_/|)
绘制多条曲线、曲线颜色、线型、标记等参数设置
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
yy=[1,2,3,4,5,3,1,2,7,8] #随便创建的数据
xx=[3,5,4,1,9,3,2,5,6,3]
zz=[2,2,4,7,4,8,2,4,5,6]
plt.plot(yy, color='r', linewidth=5, linestyle=':', label='Data 1')
plt.plot(xx, color='g', linewidth=2, linestyle='--', label='Data 2')
plt.plot(zz,color='b', linewidth=0.5, linestyle='-', label='Data 3')
plt.legend(loc=2)
plt.xlabel('X轴名称', fontproperties='simhei')
plt.ylabel('Y轴名称', fontproperties='simhei')
plt.title('折线图美化示例', fontproperties='simhei')
plt.ylim(0,10)
2.1.2 折线图实战一
已知王府井某小吃店 2018 年每个月份的营业额如下表所示。请使用matplotlib 扩展库编写 Python 程序绘制折线图对该小吃店全年营业额进行可视化,并使用红色点划线连接每个月份的数据,并在每个月份的数据处使用三角形标记。
月份 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
营业额(万元) | 5.2 | 7.7 | 5.8 | 5.7 | 7.3 | 9.2 | 18.7 | 14.6 | 20.5 | 17.0 | 9.8 | 6.9 |
小吃店营业额折线图
import matplotlib.pyplot as plt
month = list(range(1,13))
money = [5.2, 2.7, 5.8, 5.7, 7.3, 9.2,18.7, 15.6, 20.5, 18.0, 7.8, 6.9]
plt.plot(month, money, 'b-.^')
plt.xlabel('月份', fontproperties='simhei', fontsize=14)
plt.ylabel('营业额(万元)', fontproperties='simhei', fontsize=14)
plt.title('小吃店2018年营业额变化趋势图', fontproperties='simhei', fontsize=18)
plt.tight_layout() # 紧缩四周空白,扩大绘图区域可用面积
plt.show()
2.2 散点图实战
2.2.1 散点图方法
- 在 matplotlib 中使用函数 matplotlib.pyplot.scatter 绘制散点图。
matplotlib.pyplot.scatter(x, y, s=None, c=None, marker=None, cmap=None, norm=None, vmin=None, vmax=None, alpha=None, linewidths=None, verts=None, edgecolors=None, hold=None, data=None, **kwargs)
- 常用参数有:x,y 组成了散点的坐标;s 为散点的面积;c 为散点的颜色(默认为蓝色 ‘b’);marker 为散点的标记;alpha 为散点的透明度(0 与 1 之间的数,0 为完全透明, 1 为完全不透明); linewidths 为散点边缘的线宽;如果 marker 为 None,则使用 verts 的值构建散点标记;edgecolors 为散点边缘颜色。
2.2.2 绘制普通散点图
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
# 10个点
N = 10
x = np.random.rand(N)
y = np.random.rand(N)
plt.scatter(x, y)
plt.show()
2.2.3 更改散点大小
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
# 10个点
N = 10
x = np.random.rand(N)
y = np.random.rand(N)
# 每个点随机大小
s = (30*np.random.rand(N))**2
plt.scatter(x, y, s=s)
plt.show()
2.2.4 更改散点颜色、透明度
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
# 10个点
N = 10
x = np.random.rand(N)
y = np.random.rand(N)
# 每个点随机大小
s = (30*np.random.rand(N))**2
# 随机颜色
c = np.random.rand(N)
plt.scatter(x, y, s=s, c=c, alpha=0.5)
plt.show()
2.2.5 更改散点形状
import matplotlib.pyplot as plt
import numpy as np
# 10个点
N = 10
x = np.random.rand(N)
y = np.random.rand(N)
s = (30*np.random.rand(N))**2
c = np.random.rand(N)
plt.scatter(x, y, s=s, c=c, marker='^', alpha=0.5)
plt.show()
2.2.6 一张图绘制两组数据的散点图
import matplotlib.pyplot as plt
import numpy as np
# 10个点
N = 10
x1 = np.random.rand(N)
y1 = np.random.rand(N)
x2 = np.random.rand(N)
y2 = np.random.rand(N)
plt.scatter(x1, y1, marker='o')
plt.scatter(x2, y2, marker='^')
plt.show()
2.2.7 为散点图增加图例
import matplotlib.pyplot as plt
import numpy as np
# 10个点
N = 10
x1 = np.random.rand(N)
y1 = np.random.rand(N)
x2 = np.random.rand(N)
y2 = np.random.rand(N)
plt.scatter(x1, y1, marker='o', label="circle")
plt.scatter(x2, y2, marker='^', label="triangle")
plt.legend(loc='best')
plt.show()
3、柱状图、饼状图实战
3.1 柱状图实战
3.1.1 柱状图
使用 Matplotlib 提供的 bar() 函数来绘制柱状图。
与前面介绍的 plot() 函数类似,程序每次调用 bar() 函数时都会生成一组柱状图, 如果希望生成多组柱状图,则可通过多次调用 bar() 函数来实现。
只要将 bar() 函数理解透彻,我们就能绘制各种类型的柱状图。
3.1.2 柱状图 绘图方法 bar()
bar(x, height, width=0.8, *, align='center', **kwargs)
- 主要参数:
1)x:包含所有柱子的下标的列表。
2)height:y 轴的数值序列,也是柱状图的高度,一般就是我们需要展示的数据。
3)width:为柱状图的宽度,一般这是为 0.8 即可。
4)align:柱子对齐方式,有两个可选值:center 和 edge。center 表示每根柱子是根据下标来对齐, edge 则表示每根柱子全部以下标为起点,然后显示到下标的右边。如果不指定该参数,默认值是 center。 - 可选参数:
1)color:每根柱子呈现的颜色,可指定一个固定值或者一个列表。
2)edgecolor:每根柱子边框的颜色。
3)linewidth:每根柱子的边框宽度。如果没有设置该参数,默认无边框。
4)tick_label:每根柱子上显示的标签,默认无标签。
5)xerr:每根柱子顶部在横轴方向的线段长度。
6)yerr:每根柱子顶端在纵轴方向的线段长度。
7)ecolor:设置 xerr 和 yerr 的线段的颜色,可以指定一个固定值或者一个列表。
3.1.3 柱状图实战:利用 pandas 快速绘制
某商场2018年各部门每个月的业绩如下表所示(单位:万元)。编写程序绘制柱状图可视化各部门的业绩,可以借助于 pandas 的DataFrame 结构快速绘制图形,并要求坐标轴、标题和图例以中文形式显示。
月份 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
男装 | 51 | 32 | 58 | 57 | 30 | 46 | 38 | 38 | 40 | 53 | 58 | 50 |
女装 | 70 | 30 | 48 | 73 | 82 | 80 | 43 | 25 | 30 | 49 | 79 | 60 |
餐饮 | 60 | 40 | 46 | 50 | 57 | 76 | 70 | 33 | 70 | 61 | 49 | 45 |
化妆品 | 110 | 75 | 130 | 80 | 83 | 95 | 87 | 89 | 96 | 88 | 86 | 89 |
金银首饰 | 143 | 100 | 89 | 90 | 78 | 129 | 100 | 97 | 108 | 152 | 96 | 87 |
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
data = pd.DataFrame({
'月份': [1,2,3,4,5,6,7,8,9,10,11,12],
'男装': [51,32,58,57,30,46,38,38,40,53,58,50],
'女装': [70,30,48,73,82,80,43,25,30,49,79,60],
'餐饮': [60,40,46,50,57,76,70,33,70,61,49,45],
'化妆品': [110,75,130,80,83,95,87,89,96,88,86,89],
'金银首饰': [143,100,89,90,78,129,100,97,108,152,96,87]})
data.plot(x='月份', kind='bar')#绘制柱状图,指定月份数据作为x轴
plt.xlabel('月份', fontproperties='simhei') # 设置x、y轴标签和字体
plt.ylabel('营业额(万元)', fontproperties='simhei')
myfont = fm.FontProperties(fname=r'STKAITI.ttf')
plt.legend(prop=myfont)
plt.show()
3.1.4 柱状图实战:使用 matplotlib 绘制
- 简单柱状图
import matplotlib.pyplot as plt
num_list = [1.5,0.6,7.8,6]
plt.bar(range(len(num_list)), num_list)
plt.show()
设置标签
import matplotlib.pyplot as plt
name_list = ['Monday','Tuesday','Friday','Sunday']
num_list = [1.5,0.6,7.8,6]
plt.bar(range(len(num_list)), num_list, color='rgb', tick_label=name_list)
plt.show()
- 条形柱状图
设置标签
import matplotlib.pyplot as plt
name_list = ['Monday','Tuesday','Friday','Sunday']
num_list = [1.5,0.6,7.8,6]
plt.barh(range(len(num_list)), num_list,color='rgb',tick_label=name_list)
plt.show()
3.1.5 柱状图实战:使用 matplotlib 绘制
- 堆叠柱状图
import matplotlib.pyplot as plt
name_list = ['Monday','Tuesday','Friday','Sunday']
num_list = [1.5,0.6,7.8,6]
num_list1 = [1,2,3,1]
plt.bar(range(len(num_list)), num_list, label='boy', fc = 'y')
plt.bar(range(len(num_list)), num_list1, bottom=num_list, label='girl', tick_label = name_list, fc = 'r')
plt.legend()
plt.show()
- 并列柱状图
import matplotlib.pyplot as plt
name_list = ['Monday','Tuesday','Friday','Sunday']
num_list = [1.5,0.6,7.8,6]
num_list1 = [1,2,3,1]
x =list(range(len(num_list)))
total_width, n = 0.8, 2
width = total_width / n
plt.bar(x, num_list, width=width, label='boy',fc = 'y')
for i in range(len(x)):
x[i] = x[i] + width
plt.bar(x, num_list1, width=width, label='girl', tick_label = name_list, fc = 'r')
plt.legend()
plt.show()
3.2 饼状图实战
3.2.1 饼状图
概念:
1)饼状图显示一个系列中各项的大小与各项总和的比例。
2)饼状图可自动根据数据的百分比画饼。绘制饼状图的基本语法
1)创建数组 x 的饼图,每个楔形的面积由 x/sum(x) 决定;
2)若 sum(x)<1,则 x 数组不会被标准化,x 值即为楔形区域面积占比。注意,该种情况会出现 1-sum(x) 的空楔形。
3)若 sum(x)>1,则由 x[i]/sum(x) 算出每一个楔形占比,饼图 360° 区域均被填充。
3.2.2 饼状图绘图方法 pie()
pie(x, explode=None, labels=None, colors=None, autopct=None, pctdistance=0.6, shadow=False, labeldistance=1.1, startangle=None, radius=None,
counterclock=True, wedgeprops=None, textprops=None, center=(0,0),frame=False, rotatelabels=False, hold=None, data=None)
参数详解
1)x:(创建饼状图的数据,每一块) 的比例,如果 sum(x) >1 会使用 sum(x) 归一化。
2)explode:(每一块)离开中心距离,一个 list 或数组。
3)labels:list, optional, default:None;为每个楔形添加标签。
4)color:array-like, optional, default:None;若无,则用 currently active cycle 中的颜色添加。
5)autopct:控制饼图内百分比设置,可以使用 format 字符串或者format function:可以是整数(‘%d%%’)、浮点数(%1.3f%%’)、字符串(‘%s%%’)、函数。
6)label distance:float, optional, default:1.1;label 标记的绘制位置,相对于半径的比例,默认值为 1.1,如 <1 则绘制在饼图内侧。
7)pctdistance:float, optional, default:0.6;类似于 labeldistance,指定 autopct 的位置刻度,默认值为0.6。
8)shadow:bool, optional, default:False;为饼状图画阴影(True)。
9)startangle : float, optional, default: None;起始绘制角度,默认图是从 x 轴正方向逆时针画起,如设定=90则从 y 轴正方向画起。
10)radius : float, optional, default: None;饼图的半径,若为None时,则默认为 1。
11)counterclock : bool, optional, default: True;指定分数方向,逆时针 (True) 或顺时针。
12)wedgeprops : dict, optional, default: None;描述楔形边界线宽度值,参数形式’’wedgeprops = {‘linewidth’: 3}’’楔形边界线宽度为 3。
13)textprops : dict, optional, default: None;传递给文本对象的字典参数。
14)center : list of float, optional, default: (0, 0);图标的中心为,默认(0,0),也可以是两个标量的序列(sequence of 2 scalars)。
3.2.3 饼状图实战
- 简单饼状图
import matplotlib.pyplot as plt
# 用来正常显示中文标签
plt.rcParams['font.sans-serif']=['SimHei']
labels = 'A','B','C','D'
sizes = [10,20,30,40]
plt.pie(sizes,labels=labels)
plt.title("饼状图实战")
plt.text(1,-1.2,'By hsiehchou')
plt.show()
- explode : 一块饼图离开中心距离,默认值为(0,0),就是不离开中心。
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei'] # 用来正常显示中文标签
labels = 'A','B','C','D'
sizes = [10,20,30,40]
explode = (0,0,0.1,0) #将第三块分离出来
plt.pie(sizes, labels=labels, explode=explode) # 增加explode参数
plt.title("饼状图实战")
plt.text(1,-1.2,'By hsiehchou')
plt.show()
- colors:数组,可选参数,默认为:None;用来标注每块饼图的 matplotlib 颜色。
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei']
labels = 'A','B','C','D'
sizes = [10,20,30,40]
explode = (0,0,0.1,0)
colors = ['r','g','y','b'] #自定义颜色列表
plt.pie(sizes, labels=labels, explode=explode, colors=colors)
plt.title("饼状图实战")
plt.text(1,-1.2,'By hsiehchou')
plt.show()
- autopct:控制饼图内百分比设置,可以使用 format 字符串或者format function。
‘%1.1f’:指小数点后保留一位有效数值。
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei']
labels = 'A','B','C','D'
sizes = [10,20,30,40]
explode = (0,0,0.1,0)
colors = ['r','g','y','b'] #自定义颜色列表
#plt.pie(sizes,labels=labels,explode=explode,colors=colors, autopct='%1.1f') #保留一位小数
plt.pie(sizes,labels=labels,explode=explode,colors=colors, autopct='%1.2f%%') #保留两位小数,增加百分号
plt.title("饼状图实战")
plt.text(1,-1.2,'By hsiehchou')
plt.show()
- x:每一块饼图的比例,为必填项,如果 sum(x)>1,会将多出的部分进行均分;如为必填项,如果 sum(x)<1,1-sum(x) 的部分空出;
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei']
labels = 'A','B','C','D'
# sizes = [0.1,0.2,0.3,0.4] # sum(x) == 1
# sizes = [0.1,0.2,0.3,0.9] # sum(x) > 1
sizes = [0.1,0.2,0.3,0.2] # sum(x) < 1
explode = (0,0,0.1,0)
colors = ['r','g','y','b'] #自定义颜色列表
plt.pie(sizes,labels=labels,explode=explode,colors=colors, autopct='%1.1f') #保留一位小数
plt.title("饼状图实战")
plt.text(1,-1.2,'By hsiehchou')
plt.show()
- 添加图例,plt.legend( )
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei']
labels = 'A','B','C','D'
sizes = [0.1,0.2,0.3,0.4] # sum(x) == 1
explode = (0,0,0.1,0)
plt.pie(sizes,labels=labels,explode=explode, autopct='%1.1f')
plt.legend(loc="upper right", fontsize=10, bbox_to_anchor=(1.1,1.05), borderaxespad=0.3)
# bbox_to_anchor=[0.5, 0.5] # 外边距 上边 右边
# borderaxespad = 0.3图例的内边距
plt.title("饼状图实战")
plt.text(1,-1.2,'By hsiehchou')
plt.show()
3.2.4 饼状图实战二:学生成绩分布饼状图
已知某高校某班级的操作系统、高等数学、英语和 Python 课程考试成绩如下表所示,要求利用 matplotlib 库绘制饼状图显示该班级每门课的成绩中优(85分以上)、及格(60-84分)、不及格(60分以下)的学生占比。
课程/学生 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
操作系统 | 89 | 70 | 49 | 87 | 92 | 84 | 73 | 71 | 78 | 81 | 90 | 37 | 77 | 82 | 75 | 90 |
高等数学 | 70 | 74 | 80 | 60 | 50 | 87 | 68 | 77 | 95 | 80 | 79 | 74 | 69 | 64 | 82 | 81 |
英语 | 83 | 87 | 69 | 55 | 80 | 89 | 96 | 81 | 83 | 90 | 54 | 70 | 79 | 66 | 85 | 82 |
Python | 90 | 60 | 82 | 79 | 88 | 92 | 85 | 87 | 89 | 71 | 45 | 50 | 80 | 81 | 87 | 93 |
from itertools import groupby
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['simhei']
# 每门课程的成绩用字典存储
scores = {
'操作系统':[89,70,49,87,92,84,73,62,78,81,90,65,77,82,81,79,80],
'高等数学':[70,74,80,60,50,87,68,77,95,80,79,74,69,64,82,81],
'英语':[83,87,69,55,80,89,96,81,83,90,54,70,79,66,85,82],
'Python编程':[90,60,82,79,88,92,85,87,89,71,45,50,80,81,87,93]}
# 自定义分组函数,在下面的groupby()函数中使用
def splitScore(score):
if score>=85:
return '优'
elif score>=70:
return '良'
elif score>=60:
return '及格'
else:
return '不及格'
# 统计每门课程中优、及格、不及格的人数
# ratios的格式为{'课程名称':{'优':3, '及格':5, '不及格':1},...}
ratios = dict()
for subject, subjectScore in scores.items():
ratios[subject] = {}
# groupby()函数需要对原始分数进行排序才能正确分类
for category, num in groupby(sorted(subjectScore), splitScore):
ratios[subject][category] = len(tuple(num))
# 创建4个子图
fig, axs = plt.subplots(2,2)
axs.shape = 1,4
# 依次在4个子图中绘制每门课程的饼状图
for index, subjectData in enumerate(ratios.items()):
# 选择子图
plt.sca(axs[0][index])
subjectName, subjectRatio = subjectData
plt.pie(list(subjectRatio.values()), # 每个扇形对应的书
labels=list(subjectRatio.keys()), # 每个扇形的标签
autopct='%1.1f%%') # 百分比显示格式
plt.xlabel(subjectName)
plt.gca().set_aspect('equal')
plt.text(1,-1.2,'By hsiehchou')
plt.show()
4、雷达图、三维实战
4.1 雷达图实战
4.1.1 雷达图
雷达图(Radar Chart),又蜘蛛网图(Spider Chart),可以很好刻画出某些指标的横向或纵向的对比关系。
雷达图常用于对多项指标的全面分析。比如:HR 想要比较两个应聘者的综合素质,用雷达图分别画出来,就可以进行直观的比较。
python 中用 matplotlib 模块绘制雷达图需要用到极坐标系。
4.1.2 雷达图之极坐标系
在平面内取一个定点 O,叫
极点
,引一条射线 Ox,叫做极轴
,再选定一个长度单位和角度的正方向(通常取逆时针方向)。对于平面内任何一点 M,用 ρ 表示线段 OM 的长度(有时也用 r 表示),θ 表示从 Ox 到 OM 的角度,ρ 叫做点 M 的极径
,θ 叫做点 M 的极角
,有序数对 (ρ,θ) 就叫点 M 的极坐标
,这样建立的坐标系叫做极坐标系
。通常情况下,M 的极径坐标单位为 1(长度单位),极角坐标单位为 °。
4.1.3 雷达图之 polar 函数
polar(theta, r, **kwargs)
1. 主要参数:
➢ theta:指极角θ。
➢ r:指极径。
import numpy as np
import matplotlib.pyplot as plt
plt.polar(0.25*np.pi, 20, 'ro', lw=2)
plt.ylim(0,50) #设置极轴的上下限
plt.show()
注:
0.25*np.pi=45°:极角
20:极径
’ro’:绘极坐标形状为红色圆点
lw=2:极坐标图形宽度为 2
2. 如果绘制多个极角和极轴
import numpy as np
import matplotlib.pyplot as plt
theta = np.array([0.25,0.5,0.75,1,1.25,1.5,1.75,2])
r = [75,60,50,70,50,85,45,70]
plt.polar(theta*np.pi, r, 'ro', lw=2)
plt.ylim(0,100)
plt.show()
注:
theta:定义了一个 ndarray 数组存储多个数据
r:定义了一个数组存放极轴的长度,也叫极径
则在图中绘制出多个点:(0.25π,75),(0.5π, 60),(0.75π,50),(1.0π,70)等。
绘制完极坐标点后,把每个点用线连起来,就是雷达图了。
只需要把图形绘制样式修改为 ‘ro-’ 即可.
import numpy as np
import matplotlib.pyplot as plt
theta = np.array([0.25,0.5,0.75,1,1.25,1.5,1.75,2])
r = [75,60,50,70,50,85,45,70]
plt.polar(theta*np.pi, r, 'ro-', lw=2)
plt.ylim(0,100)
plt.show()
注:
’ro-’:其中-表示极坐标点之间的连线
- 闭合曲线:多构造一个极坐标点,和第一个点重叠。
import numpy as np
import matplotlib.pyplot as plt
theta = np.array([0.25,0.5,0.75,1,1.25,1.5,1.75,2,0.25])
r = [75,60,50,70,50,85,45,70,75]
plt.polar(theta*np.pi, r, 'ro-', lw=2)
plt.ylim(0,100)
plt.show()
注:
最后一个极坐标点与第一个参数相同:(0.25, 75)
- fill() 函数填充雷达图。
import numpy as np
import matplotlib.pyplot as plt
theta = np.array([0.25,0.5,0.75,1,1.25,1.5,1.75,2,0.25])
r = [75,60,50,70,50,85,45,70,75]
plt.polar(theta*np.pi, r, 'ro-', lw=2)
plt.fill(theta*np.pi, r, facecolor='r', alpha=0.25) #填充
plt.ylim(0,100)
plt.show()
4.1.4 实战:学生课程成绩雷达图
一般来说,大学的学位证只能证明学生达到该学习阶段的最低要求,并不能体现学生的综合能力以及擅长的学科与领域,因此用人单位在招聘时往往还需要借助于成绩单进行综合考察。如果把每个学生的专业核心课成绩绘制成雷达图印在学位证书上,就可让用人单位非常直观地了解学生综合能力。编写程序,根据某学生的部分专业核心课程和成绩清单绘制雷达图。
科目 | C++ | Python | 高等数学 | 大学英语 | 软件工程 | 组成原理 | 操作系统 | 网络工程 |
---|---|---|---|---|---|---|---|---|
成绩 | 82 | 95 | 72 | 85 | 45 | 58 | 65 | 86 |
import numpy as np
import matplotlib.pyplot as plt
# 某学生的课程与成绩
courses = ['C++', 'Python', '高等数学', '大学英语', '软件工程', '组成原理', '操作系统', '网络工程']
scores = [82, 95, 72, 85, 45, 58, 65, 86]
dataLength = len(scores) # 数据长度
# angles 数组把圆周等分为 dataLength 份
angles = np.linspace(0, # 数组第一个数据
2*np.pi, # 数组最后一个数据
dataLength, # 数组中数据数量
endpoint=False) # 不包含终点
scores.append(scores[0])
angles = np.append(angles, angles[0]) # 闭合
# 绘制雷达图
plt.polar(angles, # 设置角度
scores, # 设置各角度上的数据
'rv--', # 设置颜色、线型和端点符号
linewidth=2) # 设置线宽
# 设置角度网格标签
plt.thetagrids(angles*180/np.pi, courses, fontproperties='simhei') # 填充雷达图内部
plt.fill(angles, scores, facecolor='r', alpha=0.5)
plt.show()
4.2 三维图实战
4.2.1 三维图概述
matplotlib 支持一些基础的三维图表绘制,比如曲面图散点图和柱状图,需要使用 mpl_toolkits 模块。
如果要绘制三维图形,首先需要使用下面的语句导入相应的对象:
➢ from mpl_toolkits.mplot3d import Axes3D然后使用下面的两种方式之一声明要创建三维子图:
➢ ax = fig.gca(projection=’3d’)
➢ ax = plt.subplot(111, projection=’3d’)接下来就可以使用 ax 的 plot() 方法绘制三维曲线、plot_surface() 方法绘制三维曲面、 scatter() 方法绘制三维散点图或 bar3d() 方法绘制三维柱状图了。
4.2.2 三维曲面绘制方法: p3d.Axes3D. plot_surface()
- 在绘制三维图形时,至少需要指定x、y、z三个坐标轴的数据,然后再根据不同的图形类型指定额外的参数设置图形的属性。
plot_surface(X, Y, Z, *args, **kwargs)
- 常用参数:
➢ rstride 和 cstride 分别控制 x 和 y 两个方向的步长,这决定了曲面上每个面片的大小;
➢ color 用来指定面片的颜色;
➢ cmap 用来指定面片的颜色映射表。
4.2.3 三维散点图绘制方法:p3d.Axes3D.scatter()
p3d.Axes3D.scatter (xs, ys, zs=0, zdir='z', s=20, c=None, depthshade=True, *args, **kwargs)
常用参数
➢ xs、ys、zs 分别用来指定散点符号的 x、y、z 坐标,如果同时为标量则指定一个三点符号的坐标,如果同时为等长数组则指定一系列散点符号的坐标。
➢ s 用来指定散点符号的大小,可以是标量或与 xs 等长的数组。
4.2.4 三维柱状图绘制方法:p3d.Axes3D. bar3d()
p3d.Axes3D. bar3d(x, y, z, dx, dy, dz, color=None, zsort='average', *args, **kwargs)
常用参数
➢ x、y、z 分别用来指定每个柱底面的坐标,如果这三个参数都是标量则指定一个柱的底面坐标,如果是三个等长的数组则指定多个柱的底面坐标。
➢ dx、dy、dz 分别用来指定柱在三个坐标轴上的跨度,即 x 方向的宽度、y 方向的厚度和 z 方向的高度。
➢ color 用来指定柱的表面颜色。
4.2.5 三维曲线图实战
- 生成测试数据 x、y、z,然后绘制三维曲线,并设置图例的字体和字号。
import numpy as np
import matplotlib as mpl
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
# 绘制三维图形
fig = plt.figure()
ax = fig.gca(projection='3d')
# 生成测试数据
theta = np.linspace(-4 * np.pi, 4 * np.pi, 100)
z = np.linspace(-4, 4, 100)*0.3
r = z**4 + 1
x = r * np.sin(theta)
y = r * np.cos(theta)
# 绘制三维曲线,设置标签
ax.plot(x, y, z, 'bv-', label='参数曲线')
# 设置图例字体、字号,显示图例
font = fm.FontProperties(fname=r'C:\Users\hsiehchou\.spyder-py3\STKAITI.ttf')
mpl.rcParams['legend.fontsize'] = 10
ax.legend(prop=font)
plt.show()
- 生成测试数据 x、y、z,然后绘制三维曲线,并设置图例的字体和字号。
import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d
# 生成测试数据,在x和y方向分布生成-2到2之间的20个数# 步长使用虚数,虚部表示点的个数,并且包含end
x, y = np.mgrid[-2:2:20j, -2:2:20j]
z = 50 * np.sin(x+y*2)
# 创建三维图形
ax = plt.subplot(111, projection='3d')
# 绘制三维曲面
ax.plot_surface(x,y,z, rstride=3, cstride=2, cmap=plt.cm.coolwarm)
# 设置坐标轴标签
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
# 设置图形标题
ax.set_title('三维曲面', fontproperties='simhei', fontsize=24)
plt.show()
- 生成测试数据,绘制三维柱状图,设置每个柱的颜色随机,且宽度和厚度都为 1。
import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d
x = np.random.randint(0, 40, 10)
y = np.random.randint(0, 40, 10)
z = 80*abs(np.sin(x+y))
ax = plt.subplot(projection='3d')
for xx, yy, zz in zip(x, y, z):
color = np.random.random(3)
ax.bar3d(xx, yy, 0, dx=1, dy=1, dz=zz, color=color)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
plt.show()