第五章 Python 数据可视化


第五章 Python 数据可视化

1、Matplotlib 基础

1.1 Matplotlib 库介绍

  1. Matplotlib 是 Python 最著名的绘图库,它提供了一整套和 Matlab 相似的命令 API,十分适合交互式地进行制图。而且也可以方便地将它作为绘图控件,嵌入 GUI 应用程序中。

  2. Matplotlib 库由各种可视化类构成,内部结构复杂。

  3. Matplotlib.pyplot 是绘制各类可视化图形的命令字库,相当于快捷方式。

  4. Matplotlib 文档相当完备,并且 Gallery 页面中有上百幅缩略图,打开之后都有源代码。因此如果你需要绘制某种类型的图,只需要在这个页面中浏览、复制、 粘贴一下,基本上通过修改数据和设置都能搞定。

1.1.1 Matplotlib 库效果

https://matplotlib.org/gallery/index.html

Matplotlib 库

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()

Gallery 示例
或者新版本代码

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()

Gallery 示例

1.2 Matplotlib 快速绘图

1.2.1 快速绘图
  1. matplotlib 中的快速绘图的函数库可以通过如下语句载入:

import matplotlib.pyplot as plt

  1. 接下来调用 figure 创建一个绘图对象,并且使它成为当前的绘图对象:

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

  1. 通过 figsize 参数可以指定绘图对象的宽度和高度,单位为英寸; dpi 参数指定绘图对象的分辨率,即每英寸多少个像素,缺省值为 80 。

  2. 也可以不创建绘图对象直接调用接下来的 plot 函数直接绘图,matplotlib 会自动创建一个绘图对象。

  3. 在使用 Jupyter Notebook 环境绘图时,需要先运行 Jupyter Notebook 的魔术命令 %matplotlib inline。这条命令的作用是将 Matplotlib 绘制的图形嵌入在当前页面中。而在桌面环境中绘图时,不需要添加此命令,而是在全部绘图代码之后追加plt.show()

%matplotlib inline

  1. 如果需要同时绘制多幅图表的话,可以是给 figure 传递一个整数参数指定图标的序号,如果所指定序号的绘图对象已经存在的话,将不创建新的对象,而只是让它成为当前绘图对象。

  2. plot 函数的调用方式很灵活,使用关键字参数指定各种属性:
    ➢ label: 给所绘制的曲线一个名字 , 此名字在图示 (legend) 中显示 。 只要在字符串前后添加 “$” 符号 , matplotlib 就会使用其内嵌的latex 引擎绘制的数学公式;
    ➢ color: 指定曲线的颜色;
    ➢ linewidth: 指定曲线的宽度;
    ➢ 参数 b --指定曲线的颜色和线型

  3. 可通过一系列函数设置绘图对象的各个属性:
    ➢ 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() 
  1. 可以调用 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 库使用初探

  1. 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() 绘制数据日期
  1. pyplot 的绘图区域
    1)可以用子图来将图样(plot)放在均匀的坐标网格中。
    2)plt.subplot(nrows, ncols, plot_number)。
    3)用 subplot 函数的时候,需要指明网格的行列数量,以及你希望将图样放在哪一个网格区域中。

  2. 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()

pyplot的绘图区域示例

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()

pyplot的绘图区域示例

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()

pyplot的绘图区域示例

2、折线图、散点图实战

2.1 折线图实战

2.1.1 折线图
  1. 折线图通常用来表示数据随时间或有序类别变化的趋势。
  2. 最简单的折线图示例。
import matplotlib.pyplot as plt

data=[1,2,3,4,5,4,2,4,6,7] # 随意创建的数据
plt.plot(data) # 引用matplotlib库中的pyplot模块绘图
plt.show()

折线图

  1. 折线图通常用来表示数据随时间或有序类别变化的趋势。

  2. plot() 函数的第一个参数表示横坐标数据

  3. 第二个参数表示纵坐标数据

  4. 第三个参数表示颜色、线型和标记样式

  5. 颜色常用的值有(r/g/b/c/m/y/k/w)

  6. 线型常用的值有(-/–/:/-.)

  7. 标记样式常用的值有(/medias/,/o/v/^/s/*/D/d/x/</>/h/H/1/2/3/4/_/|)

  8. 绘制多条曲线、曲线颜色、线型、标记等参数设置

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 散点图方法
  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)
  1. 常用参数有: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 柱状图
  1. 使用 Matplotlib 提供的 bar() 函数来绘制柱状图。

  2. 与前面介绍的 plot() 函数类似,程序每次调用 bar() 函数时都会生成一组柱状图, 如果希望生成多组柱状图,则可通过多次调用 bar() 函数来实现。

  3. 只要将 bar() 函数理解透彻,我们就能绘制各种类型的柱状图。

3.1.2 柱状图 绘图方法 bar()
bar(x, height, width=0.8, *, align='center', **kwargs) 
  1. 主要参数:
    1)x:包含所有柱子的下标的列表。
    2)height:y 轴的数值序列,也是柱状图的高度,一般就是我们需要展示的数据。
    3)width:为柱状图的宽度,一般这是为 0.8 即可。
    4)align:柱子对齐方式,有两个可选值:center 和 edge。center 表示每根柱子是根据下标来对齐, edge 则表示每根柱子全部以下标为起点,然后显示到下标的右边。如果不指定该参数,默认值是 center。
  2. 可选参数:
    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 绘制
  1. 简单柱状图
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() 

柱状图设置标签

  1. 条形柱状图

设置标签

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 绘制
  1. 堆叠柱状图
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() 

堆叠柱状图

  1. 并列柱状图
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. 概念:
    1)饼状图显示一个系列中各项的大小与各项总和的比例。
    2)饼状图可自动根据数据的百分比画饼。

  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 饼状图实战
  1. 简单饼状图
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()

简单饼状图

  1. 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()

一块饼图离开中心距离

  1. 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()

标注每块饼图的 matplotlib 颜色

  1. 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()

饼图内百分比设置

  1. 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()

每一块饼图的比例

  1. 添加图例,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 雷达图
  1. 雷达图(Radar Chart),又蜘蛛网图(Spider Chart),可以很好刻画出某些指标的横向或纵向的对比关系。

  2. 雷达图常用于对多项指标的全面分析。比如:HR 想要比较两个应聘者的综合素质,用雷达图分别画出来,就可以进行直观的比较。

  3. python 中用 matplotlib 模块绘制雷达图需要用到极坐标系。
    雷达图

4.1.2 雷达图之极坐标系
  1. 在平面内取一个定点 O,叫极点,引一条射线 Ox,叫做极轴,再选定一个长度单位和角度的正方向(通常取逆时针方向)。对于平面内任何一点 M,用 ρ 表示线段 OM 的长度(有时也用 r 表示),θ 表示从 Ox 到 OM 的角度,ρ 叫做点 M 的极径,θ 叫做点 M 的极角,有序数对 (ρ,θ) 就叫点 M 的极坐标,这样建立的坐标系叫做极坐标系

  2. 通常情况下,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()

雷达图之 polar 函数

注:
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:定义了一个数组存放极轴的长度,也叫极径

  1. 则在图中绘制出多个点:(0.25π,75),(0.5π, 60),(0.75π,50),(1.0π,70)等。

  2. 绘制完极坐标点后,把每个点用线连起来,就是雷达图了。

  3. 只需要把图形绘制样式修改为 ‘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-’:其中-表示极坐标点之间的连线

  1. 闭合曲线:多构造一个极坐标点,和第一个点重叠。
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)

  1. 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 三维图概述
  1. matplotlib 支持一些基础的三维图表绘制,比如曲面图散点图和柱状图,需要使用 mpl_toolkits 模块。

  2. 如果要绘制三维图形,首先需要使用下面的语句导入相应的对象:
    from mpl_toolkits.mplot3d import Axes3D

  3. 然后使用下面的两种方式之一声明要创建三维子图:
    ax = fig.gca(projection=’3d’)
    ax = plt.subplot(111, projection=’3d’)

  4. 接下来就可以使用 ax 的 plot() 方法绘制三维曲线、plot_surface() 方法绘制三维曲面、 scatter() 方法绘制三维散点图或 bar3d() 方法绘制三维柱状图了。

4.2.2 三维曲面绘制方法: p3d.Axes3D. plot_surface()
  1. 在绘制三维图形时,至少需要指定x、y、z三个坐标轴的数据,然后再根据不同的图形类型指定额外的参数设置图形的属性。
plot_surface(X, Y, Z, *args, **kwargs)
  1. 常用参数:
    ➢ 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 三维曲线图实战
  1. 生成测试数据 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()

三维曲线

  1. 生成测试数据 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. 生成测试数据,绘制三维柱状图,设置每个柱的颜色随机,且宽度和厚度都为 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()

三维柱状图


文章作者: 谢舟
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 谢舟 !
 上一篇
第六章 Python机器学习 第六章 Python机器学习
第六章 Python 机器学习1、机器学习基础1.1 机器学习分类1.1.1 机器学习定义 机器学习 (Machine Learning, ML) 是一门综合性非常强的多领域交叉学科,涉及线性代数、概率论、统计学、算法复杂度理论等多门学科。
2020-06-07
下一篇 
第四章 Python 数据处理 第四章 Python 数据处理
第四章 Python 数据处理1、numpy 数组操作1.1 numpy 库概述1.1.1 引言 Python 中用列表(list)保存一组值,可用来当作数组使用,由于列表的元素可以是任何对象,因此列表中所保存的是对象的指针。为保存一个简单
2020-06-04
  目录