matplotlib入门实战全教程

Abstract:matplotlib入门实战全教程,教你如何绘制条形图、饼图、箱线图,附代码和相关学习资料。

1.Matplotlib

Matplotlib的设计理念是能够用轻松简单的方式生成强大的可视化效果,是Python学习过程中核心库之一。

  • 用在python中绘制数组的2D图形库
  • matplotlib代码在概念上分为3个部分:
    • 1.pylab接口是由matplotlib.pylab提供的函数集,允许用户使用非常类似于MATLAB图生成代码的代码创建绘图
    • 2.matplotlib前端或API是一组重要的类,可创建和管理图形,文本,线条,图表等(艺术家教程),是一个对输出无所了解的抽象接口
    • 3.后端是设备相关的绘图设备,也称为渲染器,将前端表示转换为打印件或显示设备;后端示例:PS 创建 PostScript® 打印件,SVG 创建可缩放矢量图形打印件,Agg 使用 Matplotlib 附带的高质量反颗粒几何库创建 PNG 输出,GTK 在 Gtk+ 应用程序中嵌入 Matplotlib,GTKAgg 使用反颗粒渲染器创建图形并将其嵌入到 Gtk+ 应用程序中,以及用于 PDFWxWidgetsTkinter

2.绘制条形图(Bar Chart)

条形图实际上是用来表示分组(或离散)变量的可视化,可以使用matplotlib模块中的bar函数完成条形图的绘制。

2.1 简单垂直条形图

Example1: 2017世界国家GDP排名(见下图),我们需要用matplotlib绘制展现以下数据的条形图。后端示例:PS 创建 PostScript® 打印件,SVG 创建可缩放矢量图形打印件,Agg 使用 Matplotlib 附带的高质量反颗粒几何库创建 PNG 输出,GTK 在 Gtk+ 应用程序中嵌入 Matplotlib,GTKAgg 使用反颗粒渲染器创建图形并将其嵌入到 Gtk+ 应用程序中,以及用于 PDFWxWidgetsTkinter

world GDP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 导入绘图模块
import matplotlib.pyplot as plt
# 构建数据
GDP = [12406.8,13908.57,9386.87,9143.64]

# 中文乱码的处理
plt.rcParams['font.sans-serif'] =['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False

# 绘图
plt.bar(range(4), GDP, align = 'center',color='steelblue', alpha = 0.8)
# 添加轴标签
plt.ylabel('GDP')
# 添加标题
plt.title('四个直辖市GDP大比拼')
# 添加刻度标签
plt.xticks(range(4),['北京市','上海市','天津市','重庆市'])
# 设置Y轴的刻度范围
plt.ylim([5000,15000])

# 为每个条形图添加数值标签
for x,y in enumerate(GDP):
plt.text(x,y+100,'%s' %round(y,1),ha='center')

# 显示图形
plt.show()

以上是绘制图形的代码,运行代码得到的条形图如下:

Country Rank Graph

Example2:2017中国城市GDP排名(见下图),同样我们用matplotlib绘制展现其数据的条形图。

China City GDP

1
2
3
4
5
6
7
8
9
10
11
12
# World GDP Rank
GDP = [185691, 112182.8, 49386.4, 34666.3]
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
plt.bar(range(4), GDP, align='center',color='purple',alpha=0.5)
plt.ylabel('GDP')
plt.title('2017 World GDP Rank')
plt.xticks(range(4), ['USA', 'China', 'Japan', 'Germany'])
plt.ylim([10000, 200000])
for x,y in enumerate(GDP):
plt.text(x,y+100,'%s' %round(y,1),ha='center')
plt.show()

以上是绘制图形的代码,运行代码得到的条形图如下:

City Rank Graph

代码解释:

  • rcParams:由于matplotlib对中文的支持并不是很友好,所以需要提前对绘图进行字体的设置,即通过rcParams来设置字体,这里将字体设置为微软雅黑,同时为了避免坐标轴不能正常的显示负号,也需要进行设置;
  • bar函数指定了条形图的x轴、y轴值,设置x轴刻度标签为水平居中,条形图的填充色color为铁蓝色,同时设置透明度alpha为0.8;
  • 添加y轴标签、标题、x轴刻度标签值,为了让条形图显示各柱体之间的差异,将y轴范围设置在5000~15000;
  • 通过循环的方式,添加条形图的数值标签;

2.2 简单水平条形图

Example3:同一本书不同平台最低价比较

很多人在买一本书的时候,都比较喜欢货比三家,例如《python数据分析实战》在亚马逊、当当网、中国图书网、京东和天猫的最低价格分别为39.5、39.9、45.4、38.9、33.34。针对这个数据,我们也可以通过条形图来完成,这里使用水平条形图来显示:

1
2
3
4
5
6
7
8
9
10
11
12
# 3.Book Price Comparsion
price = [39.5, 39.9, 45.4, 38.9, 33.34]
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
plt.barh(range(5),price,align='center',color='black',alpha=0.5)
plt.xlabel('price')
plt.yticks(range(5),['Amazon','Dangdang','BooksChina','Jingdong','Tianmao'])
plt.xlim([32,47])
plt.title('Book Price Comparsion')
for x,y in enumerate(price):
plt.text(y+0.1,x,'%s' %y,va='center')
plt.show()

绘制结果:

book price

代码解读:

  • 水平条形图的绘制与垂直条形图的绘制步骤一致,只是调用了barh函数来完成。需要注意的是,条形图的数值标签设置有一些不一样,需要将标签垂直居中显示,使用va参数即可。

Example4: 同家宠物店不同品种犬价格比较

Breed
Husky(哈士奇) 39099
French Bulldog(法国斗牛犬) 5899
Golden Retriever(金毛寻回犬) 13599
Labrador Retriever(拉布拉多犬) 12399
Shiba Inu(日本柴犬) 68599
1
2
3
4
5
6
7
8
9
10
11
12
# 4.Dog Price Comparsion
price = [39099, 5899, 13599, 12399, 68599]
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
plt.barh(range(5),price,align='center',color='red',alpha=0.5)
plt.title('Dog Price Comparsion')
plt.xlabel(price)
plt.yticks(range(5),['Husky','French Bulldog','Golden Retriever','Labrador Retriever','Shiba Inu'])
plt.xlim([3000,80000])
for x,y in enumerate(price):
plt.text(y+100,x,'%s' %y,va='center')
plt.show()

绘制结果:

dog price

2.3 水平交错条形图

以上的简单垂直和水平条形图是基于离散变量的情况,针对两种离散变量的条形图我们可以用水平交错条形图和堆叠条形图,下面看如何绘制:

Example5:胡润财富榜:亿万资产超高净值家庭数

利用水平交错条形图对比2016年和2017年亿万资产超高净值家庭数(top5)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 5.胡润财富榜:亿万资产超高净值家庭数/Millions Family Amount Top5 City Distribution
import numpy as np

Y2016 = [15600,12700,11300,4270,3620]
Y2017 = [17400,14800,12000,5200,4020]
labels = ['Beijing','Shanghai','Hongkong','Shenzhen','Guangzhou']
bar_width = 0.5

plt.rcParams['font.sans-serif'] =['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False

plt.bar(np.arange(5),Y2016,label='2016',color='steelblue',alpha=0.8,width=bar_width)
plt.bar(np.arange(5) + bar_width, Y2017, label='2017', color='indianred',alpha=0.8,width=bar_width)
plt.xlabel('Top5 City')
plt.ylabel('Family Amount')
plt.xticks(np.arange(5)+bar_width,labels)
plt.ylim([2500,20000])
plt.title('Millions Family Amount Top5 City Distribution')
# 为每个条形图添加数值标签
for x2016,y2016 in enumerate(Y2016):
plt.text(x2016,y2016+100,'%s'%y2016)
for x2017,y2017 in enumerate(Y2017):
plt.text(x2017+bar_width, y2017+100, '%s' %y2017)
# 显示图例
plt.legend()
plt.show()

代码解读

  • 水平交错条形图绘制的思想很简单,就是在第一个条形图绘制好的基础上,往左移一定的距离,再去绘制第二个条形图,所以在代码中会出现两个bar函数;
  • 图例的绘制需要在bar函数中添加label参数;color和alpha参数分别代表条形图的填充色和透明度;
  • 给条形图添加数值标签,同样需要使用两次for循环的方式实现;

绘制图形:

Million Family City

3.饼图(Pie Chart)

3.1 饼图

条形图:离散变量的分布呈现

饼图:离散变量各水平占比情况(使用matplotlib库里的pie函数绘制)

3.2 pie函数参数解读

1
plt.pie(x, explode=None, labels=None, colors=None, pctdistance=0.6, shadow=False, labeldistance=1.1, startangle=None, radius=None, counterclock=True, wedgeprops=None, textprops=None, center=(0,0), frame=False)
  • x: 指定绘图的数据
  • explode:指定饼图某些部分的突出显示,即呈现爆炸式
  • labels:为饼图添加标签说明,类似于图例说明
  • colors:指定饼图的填充色
  • autopct:设置百分比格式,如’%.1f%%’为保留一位小数
  • shadow:是否添加饼图的阴影效果
  • pctdistance:设置百分比标签与圆心的距离
  • labeldistance:设置各扇形标签(图例)与圆心的距离;
  • startangle:设置饼图的初始摆放角度, 180为水平;
  • radius:设置饼图的半径大小;
  • counterclock:是否让饼图按逆时针顺序呈现, True / False;
  • wedgeprops:设置饼图内外边界的属性,如边界线的粗细、颜色等, 如wedgeprops = {‘linewidth’: 1.5, ‘edgecolor’:’green’}
  • textprops:设置饼图中文本的属性,如字体大小、颜色等;
  • center:指定饼图的中心点位置,默认为原点
  • frame:是否要显示饼图背后的图框,如果设置为True的话,需要同时控制图框x轴、y轴的范围和饼图的中心位置;

3.3 绘制饼图

Example6:芝麻信用失信用户分析

我们使用芝麻信用近300万失信人群的样本统计数据来绘制饼图,该数据显示,从受教育水平上来看,中专占比25.15%,大专占比37.24%,本科占比33.36%,硕士占比3.68%,剩余的其他学历占比0.57%。对于这样一组数据,我们该如何使用饼图来呈现呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# 6.Zhima Credit Discredited User Analysis
import matplotlib.pyplot as plt


# 设置绘图的主题风格(不妨使用R中的ggplot分隔)
plt.style.use('ggplot')

# 构造数据
edu = [0.2515,0.3724,0.3336,0.0368,0.0057]
labels = ['Secondary','Junior College','Bachelor','Master','Others']

explode = [0,0.1,0,0,0] # 用于突出显示大专学历人群
colors=['#FEB748','#EDD25D','#FE4F54','#51B4FF','#dd5555'] # 自定义颜色

# 中文乱码和坐标轴负号的处理
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False

# 将横、纵坐标轴标准化处理,保证饼图是一个正圆,否则为椭圆
plt.axes(aspect='equal')

# 控制x轴和y轴的范围
plt.xlim(0,4)
plt.ylim(0,4)

# 绘制饼图
plt.pie(x = edu, # 绘图数据
explode=explode, # 突出显示大专人群
labels=labels, # 添加教育水平标签
colors=colors, # 设置饼图的自定义填充色
autopct='%.1f%%', # 设置百分比的格式,这里保留一位小数
pctdistance=0.8, # 设置百分比标签与圆心的距离
labeldistance = 1.15, # 设置教育水平标签与圆心的距离
startangle = 180, # 设置饼图的初始角度
radius = 1.5, # 设置饼图的半径
counterclock = False, # 是否逆时针,这里设置为顺时针方向
wedgeprops = {'linewidth': 1.5, 'edgecolor':'green'},# 设置饼图内外边界的属性值
textprops = {'fontsize':12, 'color':'k'}, # 设置文本标签的属性值
center = (1.8,1.8), # 设置饼图的原点
frame = 1)# 是否显示饼图的图框,这里设置显示

# 删除x轴和y轴的刻度
plt.xticks(())
plt.yticks(())
# 添加图标题
plt.title('Zhima Credit Discredited User Analysis')

# 显示图形
plt.show()

绘制图形:

zhima Redit

4.箱线图(Boxplot)

4.1 箱线图

数值型变量可视化:箱线图、直方图、折线图、面积图、散点图等等。

箱线图一般用来展现数据的分布(如上下四分位值、中位数等),同时,也可以用箱线图来反映数据的异常情况

4.2 boxplot函数的参数解读

matplotlib包中boxplot函数的参数含义及使用方法:

1
plt.boxplot(x, notch=None, sym=None, vert=None, whis=None, positions=None, widths=None, patch_artist=None, meanline=None, showmeans=None, showcaps=None, showbox=None, showfliers=None, boxprops=None, labels=None, flierprops=None, medianprops=None, meanprops=None, capprops=None, whiskerprops=None)
  • x:指定要绘制箱线图的数据;
  • notch:是否是凹口的形式展现箱线图,默认非凹口;
  • sym:指定异常点的形状,默认为+号显示;
  • vert:是否需要将箱线图垂直摆放,默认垂直摆放;
  • whis:指定上下须与上下四分位的距离,默认为1.5倍的四分位差;
  • positions:指定箱线图的位置,默认为[0,1,2…];
  • widths:指定箱线图的宽度,默认为0.5;
  • patch_artist:是否填充箱体的颜色;
  • meanline:是否用线的形式表示均值,默认用点来表示;
  • showmeans:是否显示均值,默认不显示;
  • showcaps:是否显示箱线图顶端和末端的两条线,默认显示;
  • showbox:是否显示箱线图的箱体,默认显示;
  • showfliers:是否显示异常值,默认显示;
  • boxprops:设置箱体的属性,如边框色,填充色等;
  • labels:为箱线图添加标签,类似于图例的作用;
  • filerprops:设置异常值的属性,如异常点的形状、大小、填充色等;
  • medianprops:设置中位数的属性,如线的类型、粗细等;
  • meanprops:设置均值的属性,如点的大小、颜色等;
  • capprops:设置箱线图顶端和末端线条的属性,如颜色、粗细等;
  • whiskerprops:设置须的属性,如颜色、粗细、线的类型等;

4.3 箱线图的绘制

Example7: titanic不同等级仓位的年龄箱线图

1.整体乘客的年龄箱线图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 按舱级排序,为了后面正常显示分组盒形图的顺序
titanic.sort_values(by = 'Pclass', inplace=True)

# 通过for循环将不同仓位的年龄人群分别存储到列表Age变量中
Age = []
Levels = titanic.Pclass.unique()
for Pclass in Levels:
Age.append(titanic.loc[titanic.Pclass==Pclass,'Age'])

# 绘图
plt.boxplot(x = Age,
patch_artist=True,
labels = ['一等舱','二等舱','三等舱'], # 添加具体的标签名称
showmeans=True,
boxprops = {'color':'black','facecolor':'#9999ff'},
flierprops = {'marker':'o','markerfacecolor':'red','color':'black'},
meanprops = {'marker':'D','markerfacecolor':'indianred'},
medianprops = {'linestyle':'--','color':'orange'})

# 显示图形
plt.show()

绘制图形:

Passenger Age

结果分析:

对于所有乘客而言,从图中容易发现,乘客的平均年龄在30岁,有四分之一的人低于20岁,另有四分之一的人超过38岁,换句话说,有一半的人,年龄落在20~38岁之间;从均值(红色的菱形)略高于中位数(黄色虚线)来看,说明年龄是有偏的,并且是右偏;同时,我们也会发现一些红色的异常值,这些异常值的年龄均在64岁以上。

2.不同等级仓的年龄箱线图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 8.Different Levels of Cabin
titanic.sort_values(bu='Pclass',inplace=True)
Age = []
Levels = titanic.Pclass.unique()
for Pclass in Levels:
Age.append(titanic.loc[titanic.Pclass==Pclass,'Age'])
plt.boxplot(x=Age,
patch_artist=True,
labels=['First Class','Second Class','Third Class'],
boxprops = {'color':'black','facecolor':'#9999ff'},
flierprops = {'marker':'o','markerfacecolor':'red','color':'black'},
meanprops = {'marker':'D','markerfacecolor':'indianred'},
medianprops = {'linestyle':'--','color':'orange'})
plt.show()

# 按舱级排序,为了后面正常显示分组盒形图的顺序
titanic.sort_values(by = 'Pclass', inplace=True)

# 通过for循环将不同仓位的年龄人群分别存储到列表Age变量中
Age = []
Levels = titanic.Pclass.unique()
for Pclass in Levels:
Age.append(titanic.loc[titanic.Pclass==Pclass,'Age'])

# 绘图
plt.boxplot(x = Age,
patch_artist=True,
labels = ['First Class','Second Class','Third Class'], # 添加具体的标签名称
showmeans=True,
boxprops = {'color':'black','facecolor':'#9999ff'},
flierprops = {'marker':'o','markerfacecolor':'red','color':'black'},
meanprops = {'marker':'D','markerfacecolor':'indianred'},
medianprops = {'linestyle':'--','color':'orange'})

# 显示图形
plt.show()

绘制图形:

Pclass Age

结果分析:如果对人群的年龄按不同的舱位来看,会发现一个明显的趋势,就是舱位等级越高的乘客,他们的年龄越高,三种舱位的平均年龄为38、30和25,说明年龄越是偏大一点,他们的经济能力会越强一些,所买的舱位等级可能就会越高一些。同时,在二等舱和三等舱内,乘客的年龄上存在一些异常用户。

学习资料

Gitbook:pyplot教程

matplotlib图像教程

matplotlib艺术家教程

始终:Matplotlib 教程

Reference

从零开始学Python【1】—matplotlib(条形图)

从零开始学Python【2】—matplotlib(饼图)

从零开始学Python【3】—matplotlib(箱线图)

拿钱去买猫粮和狗粮嗷 ~