发布于 

matplotlib可视化基础

matplotlib制作可视化图表是python数据分析中的一个非常重要的模块,这个模块我之前一直没怎么使用过,这里重新练习下matplotlib模块的使用,数据源来自天池比赛中的二手车交易价格预测数据。

一、matplotlib基础

1、matplotlib图形的基本构成部分

1
2
3
4
# 一般在jupyter notebook中导入matplotlib的方式
import matplotlib as mpl
import matplotlib.pyplot as plt
%matplotlib inline #在notebook中嵌入画图
  • 基础 (primitives) 类:线 (line), 点 (marker), 文字 (text), 图例 (legend), 网格 (grid), 标题 (title), 图片 (image) 等。
  • 容器 (containers) 类:图 (figure), 坐标系 (axes), 坐标轴 (axis) 和刻度 (tick)

基础类元素是我们想画出的标准对象,而容器类元素是基础类元素的寄居出,它们也有层级结构。

图 → 坐标系 → 坐标轴 → 刻度→绘制图型

如下图所示,主要元素及结构:figure(图形)、axes(子图形)、title(标题)、legend(图例)、Major tick(大标尺刻度)、Minor tick(小标尺刻度)、Major tick label(大标尺刻度数值)、Minor tick label(小标尺刻度数值)、Y axis label(y轴指标说明)、X axis label(x轴指标说明)、Line(线型图)、Markers(数据标注点)、Grid(格子)等。

image-20200531221650861

2、matplotlib图形的几个容器类:

2.1 Figure对象(图)

整个图形即是一个Figure对象。
Figure对象至少包含一个子图,也就是Axes对象。
Figure对象包含一些特殊的Artist对象,如title标题、图例legend。
Figure对象包含画布canvas对象。 canvas对象一般不可见,通常无需直接操作该对象,matplotlib程序实际绘图时需要调用该对象。

figure对象上可以添加各种元素:文字、图片、折线等,接下来实际操作下:

1
2
3
4
5
6
7
8
# 在figure中显示文本并自定义位置
plt.figure()
plt.text(x=0.5,y=0.5,s='Figure',ha='center',va='center',size=20,alpha=0.5)
# 第一、二个参数是指横轴和纵轴坐标
# 第三个参数字符是指要显示的内容
# ha, va 是横向和纵向位置
# size 设置字体大小
# alpha 设置字体透明度 (0.5 是半透明)

1
2
3
4
5
6
7
8
# 用 Image.open() 将图片转成像素存在 ndarray 中,再用 plt.imshow() 展示。
from PIL import Image #导入图片处理模块
plt.figure()
plt.xticks([]) #将x、y的刻度置为null
plt.yticks([])
im = np.array(Image.open('111.png'))
plt.imshow(im)
plt.show()

image-20200531212320096

2.2 Subplot对象(子图)

常用方法set_xlim()以及set_ylim():设置子图x轴和y轴对应的数据范围。

set_xticks()以及set_yticks():设置子图的x轴和y轴刻度标签

set_title():设置子图的标题。

set_xlabel()以及set_ylable():设置子图x轴和y轴指标的描述说明

1
2
3
4
5
6
7
8
9
10
11
12
# subplot(rows, columns, i-th plots) 
plt.figure()
plt.subplot(2,1,1)
plt.xticks([])
plt.yticks([])
plt.text(x=0.5,y=0.5,s='subplot(2,1,1)',ha='center',va='center',size=20,alpha=0.5)
plt.subplot(2,1,2)
plt.xticks([])
plt.yticks([])
plt.text(x=0.5,y=0.5,s='subplot(2,1,2)',ha='center',va='center',size=20,alpha=0.5)
plt.show()
# 声明完子图后,下面所有代码就只在这幅子图上生效,直到声明下一幅子图

image-20200531212506334

1
2
3
4
5
6
7
8
9
# 循环绘制子图
fig,axes = plt.subplots(nrows=2,ncols=2)
# enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)
# 组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。
for i,ax in enumerate(axes.flat):
ax.set(xticks=[],yticks=[])
s = 'subplot(2,2' + str(i) + ')'
ax.text(0.5,0.5,s,size=20,alpha=0.5,ha='center',va='center')

image-20200531212515700

2.3 Axes对象(坐标系)

字面上理解,Axes是数据轴Axis的复数,但它并不是指数据轴,而是子图对象,可以这样理解,每一个子图都有x和y轴,Axes则用于代表这两个数据轴所对应的一个子图坐标系对象,我们每次画图看起来是在图(Figure)中进行,实际是绘制在Axes坐标系对象中的,一个Figure对象能有多个Axes对象。

一幅图 (Figure) 中可以有多个坐标系 (Axes),说一幅图中有多幅子图 (Subplot),因此坐标系和子图是不是同样的概念?

在绝大多数情况下是的,两者有一点细微差别:

  • 子图在母图中的网格结构一定是规则的
  • 坐标系在母图中的网格结构可以是不规则的

子图是坐标系的一个特例。

坐标系比子图更通用,有两种生成方式

  • 用 gridspec 包加上 subplot()

  • 用 plt.axes()

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
# 不规则网格
import matplotlib.gridspec as gridspec
G = gridspec.GridSpec(3,3)

ax1 = plt.subplot(G[0:1,:3]) #类似于numpy的选取方式,选取矩阵数据
plt.xticks([]),plt.yticks([])
plt.text(x=0.5,y=0.5,s='Axes 1',ha='center',va='center',size=20,alpha=0.5)

ax2 = plt.subplot(G[1:2,0:2]) #类似于numpy的选取方式,选取矩阵数据
plt.xticks([]),plt.yticks([])
plt.text(x=0.5,y=0.5,s='Axes 2',ha='center',va='center',size=20,alpha=0.5)

ax3 = plt.subplot(G[1:3,2:3]) #类似于numpy的选取方式,选取矩阵数据
plt.xticks([]),plt.yticks([])
plt.text(x=0.5,y=0.5,s='Axes 3',ha='center',va='center',size=20,alpha=0.5)

ax4 = plt.subplot(G[2:3,0:1]) #类似于numpy的选取方式,选取矩阵数据
plt.xticks([]),plt.yticks([])
plt.text(x=0.5,y=0.5,s='Axes 4',ha='center',va='center',size=20,alpha=0.5)

ax5 = plt.subplot(G[2:3,1:2]) #类似于numpy的选取方式,选取矩阵数据
plt.xticks([]),plt.yticks([])
plt.text(x=0.5,y=0.5,s='Axes 5',ha='center',va='center',size=20,alpha=0.5)

plt.show()

image-20200531214553755

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 大图套小图
plt.axes([0.1,0.1,0.8,0.8])
# plt.xticks([]),plt.yticks([])
plt.text(x=0.6,y=0.6,s='axes([0.1,0.1,0.8,0.8])',va='center',ha='center',size=20,alpha=0.5)

plt.axes([0.2,0.2,0.3,0.3])
plt.text(x=0.5,y=0.5,s='axes([0.2,0.2,0.3,0.3])',va='center',ha='center',size=10,alpha=0.5)

plt.show()
# 此时的axes对象的坐标和xticks刻度上的坐标并不一致
# plt.axes([l,b,w,h])
# 其中 [l, b, w, h] 可以定义坐标系

# l 代表坐标系左边到 Figure 左边的水平距离
# b 代表坐标系底边到 Figure 底边的垂直距离
# w 代表坐标系的宽度
# h 代表坐标系的高度
# 如果 l, b, w, h 都小于 1,那它们是标准化 (normalized) 后的距离。比如 Figure 底边长度为 10, 坐标系底边到它的垂直距离是 2,那么 b = 2/10 = 0.2。

image-20200531214621588

两种生成坐标系的推荐代码:

第一种,同时生成图和坐标系:

1
2
3
4
5
fig,ax = plt.subplots()
ax.set(xticks=[],yticks=[])
s='xxx'
ax.text(x=0.5,y=0.5,s=s,ha='center',va='center',size=20,alpha=0.5)
plt.show()

第二种,先生成图,再添加坐标系

1
2
3
4
5
6
fig=plt.figure()
ax = fig.add_subplot(1,1,1)
ax.set(xticks=[],yticks=[])
s='xxx'
ax.text(x=0.5,y=0.5,s=s,ha='center',va='center',size=20,alpha=0.5)
plt.show()

2.4 Axis对象(坐标轴)

Axis是数据轴对象,主要用于控制数据轴上刻度位置和显示数值,通常是二维的,有两条坐标轴

  • 横轴:XAxis
  • 纵轴:YAxis

每个坐标轴包含两个元素

  • 容器类元素「刻度」,该对象里还包含刻度本身刻度标签
  • 基础类元素「标签」,该对象包含的是坐标轴标签
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
fig, ax = plt.subplots()
ax.set_xlabel('x label',size=20,color='red',rotation=30)
#所有的文本对象都可以调整文字和颜色以及角度
ax.set_ylabel('t label')


for label in ax.xaxis.get_ticklabels():
# x轴的label是文本对象,都可以调整相关文本的参数,y轴同样
label.set_color('blue')
label.set_rotation(45)
label.set_fontsize(20)


for line in ax.yaxis.get_ticklines():
# y轴的line对象进行调整,线条的对象同样有类似的属性
line.set_color('green')
line.set_markersize(500)
line.set_markeredgewidth(30)

image-20200531220320757

2.5 Tick对象(刻度)

2.6 Artist对象

基本上所有的对象都是一个Artist对象,包括Figure对象、Axes对象和Axis对象,可以将Artist理解为一个基本类。当提交代码,图像最终呈现时,所有的artist对象都会绘制于canvas画布上,这个对象其实大部分时间用不上。

3、matplotlib图形的基础元素:

要画出一幅有内容的图,还需要在容器里添加基础元素比如线 (line), 点 (marker), 文字 (text), 图例 (legend), 网格 (grid), 标题 (title), 图片 (image) 等,具体来说

  • 画一条线,用 plt.plot() 或 ax.plot()
  • 画个记号,用 plt.scatter() 或 ax.scatter()
  • 添加文字,用 plt.text() 或 ax.text()
  • 添加图例,用 plt.legend() 或 ax.legend()
  • 添加图片,用 plt.imshow() 或 ax.imshow()

二、实例绘图

本实例绘图数据依据天池比赛零基础入门数据挖掘 - 二手车交易价格预测的数据源进行绘制,探索该部分数据结构。

首先读取数据

1
2
3
4
5
6
# 读取天池二手车交易价格预测的训练数据
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
dftrain = pd.read_csv(r'.\\天池二手车交易交额预测\\used_car_train_20200313.csv',sep=' ')
dftrain.head()
SaleIDnameregDatemodelbrandbodyTypefuelTypegearboxpowerkilometerv_5v_6v_7v_8v_9v_10v_11v_12v_13v_14
007362004040230.061.00.00.06012.50.2356760.1019880.1295490.0228160.097462-2.8818032.804097-2.4208210.7952920.914762
1122622003030140.012.00.00.0015.00.2647770.1210040.1357310.0265970.020582-4.9004822.096338-1.030483-1.7226740.245522
221487420040403115.0151.00.00.016312.50.2514100.1149120.1651470.0621730.027075-4.8467491.8035591.565330-0.832687-0.229963
337186519960908109.0100.00.01.019315.00.2742930.1103000.1219640.0333950.000000-4.5095991.285940-0.501868-2.438353-0.478699
4411108020120103110.051.00.00.0685.00.2280360.0732050.0918800.0788190.121534-1.8962400.9107830.9311102.8345181.923482

5 rows × 31 columns

主要指标含义如下:

train.csv

  • SaleID - 销售样本ID
  • name - 汽车编码
  • regDate - 汽车注册时间
  • model - 车型编码
  • brand - 品牌
  • bodyType - 车身类型
  • fuelType - 燃油类型
  • gearbox - 变速箱
  • power - 汽车功率
  • kilometer - 汽车行驶公里
  • notRepairedDamage - 汽车有尚未修复的损坏
  • regionCode - 看车地区编码
  • seller - 销售方
  • offerType - 报价类型
  • creatDate - 广告发布时间
  • price - 汽车价格
  • v_0’, ‘v_1’, ‘v_2’, ‘v_3’, ‘v_4’, ‘v_5’, ‘v_6’, ‘v_7’, ‘v_8’, ‘v_9’, ‘v_10’, ‘v_11’, ‘v_12’, ‘v_13’,’v_14’ 【匿名特征,包含v0-14在内15个匿名特征】  

数字全都脱敏处理,都为label encoding形式,即数字形式。

首先对数据进行常规解读:

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
dftrain.info()
# 输出:
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 150000 entries, 0 to 149999
Data columns (total 31 columns):
SaleID 150000 non-null int64
name 150000 non-null int64
regDate 150000 non-null int64
model 149999 non-null float64
brand 150000 non-null int64
bodyType 145494 non-null float64
fuelType 141320 non-null float64
gearbox 144019 non-null float64
power 150000 non-null int64
kilometer 150000 non-null float64
notRepairedDamage 150000 non-null object
regionCode 150000 non-null int64
seller 150000 non-null int64
offerType 150000 non-null int64
creatDate 150000 non-null int64
price 150000 non-null int64
v_0 150000 non-null float64
v_1 150000 non-null float64
v_2 150000 non-null float64
v_3 150000 non-null float64
v_4 150000 non-null float64
v_5 150000 non-null float64
v_6 150000 non-null float64
v_7 150000 non-null float64
v_8 150000 non-null float64
v_9 150000 non-null float64
v_10 150000 non-null float64
v_11 150000 non-null float64
v_12 150000 non-null float64
v_13 150000 non-null float64
v_14 150000 non-null float64
dtypes: float64(20), int64(10), object(1)
memory usage: 35.5+ MB
1
2
dftrain.describe().round(2)
# 输出
SaleIDnameregDatemodelbrandbodyTypefuelTypegearboxpowerkilometerv_5v_6v_7v_8v_9v_10v_11v_12v_13v_14
count150000.00150000.00150000.00149999.00150000.00145494.00141320.00144019.00150000.00150000.00150000.00150000.00150000.00150000.00150000.00150000.00150000.00150000.00150000.00150000.00
mean74999.5068349.1720034170.5147.138.051.790.380.22119.3212.600.250.040.120.060.06-0.000.010.000.00-0.00
std43301.4161103.8853649.8849.547.861.760.550.42177.173.920.050.050.200.030.043.773.292.521.291.04
min0.000.0019910001.000.000.000.000.000.000.000.500.000.000.000.000.00-9.17-5.56-9.64-4.15-6.55
25%37499.7511156.0019990912.0010.001.000.000.000.0075.0012.500.240.000.060.040.03-3.72-1.95-1.87-1.06-0.44
50%74999.5051638.0020030912.0030.006.001.000.000.00110.0015.000.260.000.100.060.061.62-0.36-0.13-0.040.14
75%112499.25118841.2520071109.0066.0013.003.001.000.00150.0015.000.270.100.130.080.092.841.261.780.940.68
max149999.00196812.0020151212.00247.0039.007.006.001.0019312.0015.000.290.151.400.160.2212.3618.8213.8511.158.66

8 rows × 30 columns

三、基础参数

参照这个GitHub地址总结的:https://github.com/rougier/matplotlib-cheatsheet

matplotlib-cheatsheet

最后

给出以上实例的jupyter notebook文件:

matplotlib基础.html

给出matplotlib的预定义格式

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
# 可视化显示在页面,包含3种
# %matplotlib inline
# %matplotlib notebook
# %matplotlib qt5


#%config InlineBackend.figure_format = 'svg' #输出矢量图,放大不失真
#原始风格
#%config InlineBackend.figure_format='retina'

# 导入所有使用到的模块,并设定matplotlib的绘图基础格式
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
%matplotlib inline

# 统一绘图格式
large = 22; med = 16; small = 12 #其余字体大小统一设置为14
params = {'axes.titlesize': large,
'legend.fontsize': med,
'figure.figsize': (15, 8),
'axes.labelsize': med,
'axes.titlesize': med,
'xtick.labelsize': med,
'ytick.labelsize': med,
'figure.titlesize': large}
plt.rcParams.update(params)
plt.style.use('seaborn-whitegrid') #更改模块风格

plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签 plt.rcParam
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
# plt.rcParams['savefig.dpi'] = 300 #保存图片像素
# plt.rcParams['figure.dpi'] = 300 #显示分辨率
# plt.rcParams['animation.embed_limit' ] = 100 #限定animation模块的最大mb


#百度 Echarts 里面的一组颜色卡
r_hex = '#dc2624' # red, RGB = 220,38,36
dt_hex = '#2b4750' # dark teal, RGB = 43,71,80
tl_hex = '#45a0a2' # teal, RGB = 69,160,162
r1_hex = '#e87a59' # red, RGB = 232,122,89
tl1_hex = '#7dcaa9' # teal, RGB = 125,202,169
g_hex = '#649E7D' # green, RGB = 100,158,125
o_hex = '#dc8018' # orange, RGB = 220,128,24
tn_hex = '#C89F91' # tan, RGB = 200,159,145
g50_hex = '#6c6d6c' # grey-50, RGB = 108,109,108
bg_hex = '#4f6268' # blue grey, RGB = 79,98,104
g25_hex = '#c7cccf' # grey-25, RGB = 199,204,207

1f271b23-5ee5-474c-a6cb-71072c907837

1
2
3
4
5
6
7
# 第二组色卡,从左往右
zhong_gray = '#8C8EA1' #RGB=140,142,161
qian_gray = '#959EC3' #RGB=149,158,195
dan_gray ='#D9DBF5' #RGB=217,219,245
qian_blue = '#3B4F88' #RGB=59,79,136
shen_black = '#0A0D1E' #RGB=10,13,30
shen_gray = '#786B7A' #RGB=120,107,122

9a78b6da-5890-4bde-9450-ff68ab4fcde5