俗话说:“文不如表,表不如图”,如果我们将海量的数据绘制成图,就可以让我们的数据更加直观的呈现,更具说服力。
在“互联网+时代”,90%的信息传到大脑,其实都是通过视觉形式来传过来的,而且可视化信息被人脑接受的速度比文字信息要快6万倍,所以,将海量的数据转换成可视化的图形是我们数据分析师必备技能。
Matplotlib是一个Python 2D绘图库,它可以在各种平台上以各种硬拷贝格式和交互式环境生成出具有出版品质的图形。
Matplotlib试图让简单的事情变得更简单,让无法实现的事情变得可能实现。也是Python中最常用的可视化工具之一,它的功能非常强大,可以通过调用函数轻松方便地绘制数据分析中常见的各种图像,比如折线图、条形图、柱状图、散点图、饼图等。
折线图:以折线的上升或下降来表示统计数量的增减变化的统计图
特点:能够显示数据的变化趋势,反映事物的变化情况。(变化)
散点图:用两组数据构成多个坐标点,考察坐标点的分布,判断两变量之间是否存在某种关联或总结坐标点的分布模式。
特点:判断变量之间是否存在数量关联趋势,展示离群点(分布规律)。
柱状图:排列在工作表的列或行中的数据可以绘制到柱状图中。
特点:绘制离散的数据,能够一眼看出各个数据的大小,比较数据之间的差别。(统计/对比)
直方图:由一系列高度不等的纵向条纹或线段表示数据分布的情况。 一般用横轴表示数据范围,纵轴表示分布情况。
特点:绘制连续性的数据展示一组或者多组数据的分布状况(统计)。
饼图:用于表示不同分类的占比情况,通过弧度大小来对比各种分类。
特点:分类数据的占比情况(占比)。
当然,除了这些常用图之外,matplotlib还可以绘制一些其它的图像,那么,这些图究竟是如何绘制的呢?
通常情况下,我们可以将一张Matplotlib图像分成三层结构:
容器层主要由Canvas、Figure、Axes组成。
Canvas是位于最底层的系统层,在绘图的过程中充当画板的角色,即放置画布(Figure)的工具,用户一般接触不到。
Figure是Canvas上方的第一层,也是需要用户来操作的应用层的第一层,在绘图的过程中充当画布的角色,我们可以设置画布的大小和分辨率等。
Axes是应用层的第二层,在绘图的过程中相当于画布上的绘图区的角色。一个Figure对象可以包含多个Axes对象,每个Axes都是一个独立的坐标系,绘图过程中的所有图像都是基于坐标系绘制的。
辅助显示层为Axes(绘图区)内的除了根据数据绘制出的图像以外的内容,主要包括Axes外观(facecolor)、边框线(spines)、坐标轴(axis)、坐标轴名称(axis label)、坐标轴刻度(tick)、坐标轴刻度标签(tick label)、网格线(grid)、图例(legend)、标题(title)等内容。
该层的设置可使图像显示更加直观,更加容易被用户理解,但又不会对图像产生实质的影响。
图像层指Axes内通过plot、scatter、bar、histogram、pie等函数根据数据绘制出的图像。
根据上面对Matplotlib的结构的拆分了解后,我们可以做出以下总结:
跟Pandas的使用一样,使用matplotlib之前,我们需要将它的模块,因为我们是使用Matplotlib的pyplot模块进行图形绘制,所以我们要导入pyplot模块。
#在使用jupyter notebook时调用matplotlib.pyplot的绘图函数plot()进行绘图的时候,或者生成一个figure画布的时候,需要加上%matplotlib
%matplotlib inline
from matplotlib import pyplot as plt
x = range(1,8)
y = [17, 17, 18, 15, 11, 11, 13]
plt.plot(x,y)
plt.show()
代码含义
那么,折线的颜色、折点以及宽度该怎么设置呢?
from matplotlib import pyplot as plt
x = range(1,8)
y = [17, 17, 18, 15, 11, 11, 13]
plt.plot(x,y,color='green',alpha=0.5,linestyle='-',linewidth=3,marker='o')
plt.show()
代码含义
对一个图形最重要的是内容的绘制,其次就是标题,我们需要让其他人清楚这张图的含义是什么,图中x轴表示什么,y轴表示什么,这个时候我们就需要为图像添加一些标题。
这些标题信息就需要我们在绘制的时候,将标题信息绘制在图片上
from matplotlib import pyplot as plt
x = range(1,8)
y = [14,13,17,15,16,10,20]
plt.plot(x,y,color='green',alpha=0.5,linestyle='-',linewidth=3,marker='o')
plt.xlabel('Time')
plt.ylabel('Temp')
plt.title('Team Changing')
plt.show()
通过以下方法添加标记:
这样就可以清晰明了地看出图片及每个轴的含义。
相信大家在练习的时候也遇到过这样的问题,使用Matplotlib画的图居然不显示中文。
实际上,matplotlib是支持unicode编码的,中文乱码的主要问题是没有找到合适的中文字体。
如果想要Matplotlib显示中文我们可以使用三种方法:
我们将讲解第三种方法,因为自定义的字体自由度比较高,同时也方便我们在一个图中使用不同风格的字体。
首先,我们下载了一个字体文件,文件的存储路径为C:\Users\lin-a\Desktop\Python数据分析\经典黑体简.TTF
在给图片设置中文显示之前我们应该先添加下面的代码:
from matplotlib import font_manager
my_font = font_manager.FontProperties(fname=r'C:\Users\lin-a\Desktop\Python数据分析\经典黑体简.TTF')
当需要有中文显示的地方,添加字体属性就可以了。
接下来我们通过一个代码来看一下,如何添加中文字体,运行下方代码:
%matplotlib inline
from matplotlib import pyplot as plt
from matplotlib import font_manager
import random
# 创建字体对象
my_font = font_manager.FontProperties(fname=r'C:\Users\lin-a\Desktop\Python数据分析\经典黑体简.TTF',size=18)
# 创建X轴与Y轴数据
x = range(0,120)
y = [random.randint(10,30) for i in range(120)]
# 添加字体属性
plt.ylabel("次数",fontproperties=my_font)
plt.xlabel("时间",fontproperties=my_font)
# 设置标题
plt.title('每分钟跳动次数',fontproperties=my_font)
plt.plot(x,y)
plt.show()
从展示图片发现,我们要的中文已经成功添加了:
当然,我们在所有需要中文的地方添加的都是同一种字体,我们可以根据需求创建更多的字体对象,还可以通过size属性设置字体的大小,这样就可以让我们的图像中文显示的更加多样化。
在上一节的第二个练习中,我们发现一个问题,x轴的刻度值全都重叠在一起了。
造成这个问题的原因是:
现在,我们先看看通过改变图片的大小能否解决重叠的问题。
要想改变图像的大小,我们需要更改画布的大小来实现,matplotlib 中设置图形大小的语句如下:
plt.figure(figsize=(a,b),dpi=dpi)
其中:
%matplotlib inline
import pandas as pd
from matplotlib import pyplot as plt
# 导入数据
path = r'C:\Users\lin-a\Desktop\data\600001SH.xlsx'
stocks = pd.read_excel(path)
print(stocks.shape)
stocks.head()
# 将日期列的值作为X轴
x = stocks['日期'].values.tolist()
# 将时间戳格式转换为“2015-01-04”的格式
x2 = [pd.to_datetime(time).strftime('%Y-%m-%d') for time in x]
# 将开盘价列的值作为Y轴
y = stocks['开盘价(元)'].values.tolist()
# 更改画布大小
plt.figure(figsize=(20,10),dpi=80)
# 绘制折线图
plt.plot(x2,y)
plt.xlabel('Time')
plt.ylabel('Price')
plt.title('Open/Time')
plt.show()
(105, 13)
我们将图形的宽和高分别设置为20,10英寸,分辨率设置为80后发现,x轴的重叠的效果减轻一些,但还是会有严重的重叠。
那我们是不是还要继续修改宽和高呢?答案肯定是No
如果继续放大,图形会变的很大,不是我们想要的效果,所以,并不是所有的刻度问题我们都可以使用改变图片的大小来解决。
前面我们学习x轴的标题是使用plt.xlabel()这个方法,接下来我要使用plt.xticks()这个方法自定义x轴的刻度。
plt.xticks(locs,[labels],**kwargs)
%matplotlib inline
import pandas as pd
from matplotlib import pyplot as plt
# 导入数据
path = r'C:\Users\lin-a\Desktop\data\600001SH.xlsx'
stocks = pd.read_excel(path)
print(stocks.shape)
stocks.head()
# 将日期列的值作为X轴
x = stocks['日期'].values.tolist()
# 将时间戳格式转换为“2015-01-04”的格式
x2 = [pd.to_datetime(time).strftime('%Y-%m-%d') for time in x]
# 将开盘价列的值作为Y轴
y = stocks['开盘价(元)'].values.tolist()
# 更改画布大小
plt.figure(figsize=(20,10),dpi=80)
# 绘制折线图
plt.plot(x2,y)
plt.xlabel('Time')
plt.ylabel('Price')
plt.title('Open/Time')
# 自定义X轴刻度显示
plt.xticks(range(700,len(x),3),x[700::3],rotation=45)
plt.show()
(105, 13)
通过上面的设置我们就可以轻松的对x轴刻度进行疏密调整,以及对应的刻度标签的设置。
range(0,len(x),3)为xticks()的第一个参数,根据x值的个数调整x轴的刻度疏密程度。
x[::3]为xticks()的第二个参数,还是使用x的值作为刻度的标签值,但是这里获取了其中的一部分,确保第一个参数和第二个参数的个数相同。
rotation=45默认刻度的值是横向书写的,这样会有一定的重叠,所以我们将文字进行旋转操作,45位旋转的度数。
通过上面的设置我们就可以轻松的对x轴刻度进行疏密调整,以及对应的刻度标签的设置。
通过以上学习,我们知道了如何自定义坐标轴的刻度。现在又提出一个需求,就是在上图中同时绘制出开盘价和收盘价。
我们知道绘制一个折线的方法是plt.plot()方法,所以,我们可以猜想一个画布上绘制两条折线,是不是使用两次plt.plot()方法就可以了呢?运行下方代码,验证我们的猜想:
%matplotlib inline
import pandas as pd
from matplotlib import pyplot as plt
# 导入数据
path = r'C:\Users\lin-a\Desktop\data\600001SH.xlsx'
stocks = pd.read_excel(path)
print(stocks.shape)
stocks.head()
# 获取X轴数据
x = stocks['日期'].values.tolist()
# 将时间戳格式转换为“2015-01-04”的格式
x2 = [pd.to_datetime(time).strftime('%Y-%m-%d') for time in x]
# 获取开盘价数据
y = stocks['开盘价(元)'].values.tolist()
# 获取收盘价的数据
z = stocks['收盘价(元)'].values.tolist()
# 设置画布大小
plt.figure(figsize=(20,10),dpi=80)
# 绘制开盘价曲线
plt.plot(x2,y)
# 绘制收盘价曲线
plt.plot(x2,z)
# 设置标签与标题
plt.xlabel('Time')
plt.ylabel('Price')
plt.title('Open/Time')
# 设置X轴的刻度
plt.xticks(range(700,len(x),3),x[700::3],rotation=45)
plt.show()
(105, 13)
一个坐标系中绘制两条折线,只需要使用两次plt.plot()方法就可以了。
但是,通过图形我们并不知道哪条线是开盘价,哪条线是收盘价,所以,我们应该在图像中添加对应的图例,从而标明每条线的作用是什么。
plt.legend()方法就是图形添加图例的方法,但是这个方法比较特殊,一共需要两步才能成功的添加上图例,我们先运行下放代码,看一下图例的效果:
%matplotlib inline
import pandas as pd
from matplotlib import pyplot as plt
from matplotlib import font_manager
my_font = font_manager.FontProperties(fname=r'C:\Users\lin-a\Desktop\Python数据分析\经典黑体简.TTF')
# 导入数据
path = r'C:\Users\lin-a\Desktop\data\600001SH.xlsx'
stocks = pd.read_excel(path)
print(stocks.shape)
stocks.head()
# 获取X轴数据
x = stocks['日期'].values.tolist()
# 将时间戳格式转换为“2015-01-04”的格式
x2 = [pd.to_datetime(time).strftime('%Y-%m-%d') for time in x]
# 获取开盘价数据
y = stocks['开盘价(元)'].values.tolist()
# 获取收盘价的数据
z = stocks['收盘价(元)'].values.tolist()
# 设置画布大小
plt.figure(figsize=(20,10),dpi=80)
# 绘制开盘价曲线
plt.plot(x2,y,label='开盘价')
# 绘制收盘价曲线
plt.plot(x2,z,label='收盘价')
# 设置图示
plt.legend(prop=my_font)
# 设置标签与标题
plt.xlabel('Time')
plt.ylabel('Price')
plt.title('Open/Time')
# 设置X轴的刻度
plt.xticks(range(700,len(x),3),x[700::3],rotation=45)
# 设置网格
plt.grid(alpha=0.5)
plt.show()
(105, 13)
通过结果发现,在图形的右上角我们成功的添加上了图例。接下来,我们一起分析一下加图例的流程。
同时,结果中我们不仅添加上了图例,在图形中我们发现了很多网格。
我们上面的学习都是在一个画布上创建一个坐标系,在上节课中我们介绍到一个画布上是可以分成多个区域,每个区域都可以绘制一个图像,这里的每个图像称为一个子图。
调用plt.subplot()函数就可以在画布上创建一个子图,plt.subplot()的使用方法如下:
plt.subplot(nrows,ncols,index)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Bf1ioqMz-1591080499558)(attachment:image.png)]
Axes1、Axes2、Axes3、Axes4分别代表四个区域。
%matplotlib inline
from matplotlib import pyplot as plt
import numpy as np
x = [1,10,14,15,16,17]
y = np.array([3,4,6,2,1,5])
plt.figure(figsize = (10,8))
# 第一个子图
# 折线图
plt.subplot(2, 2, 1)
plt.plot(y)
plt.title('Axes1')
#第二个子图
# 折线图,y轴每个数据的立方
plt.subplot(2, 2, 2)
plt.plot(y**3)
plt.title('Axes2')
#第三个子图
# 折线图,x轴和y轴均指定数据
plt.subplot(2, 2, 3)
plt.plot(x,y)
plt.title('Axes3')
plt.show()
上面我们创建一个包含2行2列,共4个子图。第一个子图的创建方法是plt.subplot(2, 2, 1),第二个子图就使用:plt.subplot(2, 2, 2),以此类推。
我们可以在 Python 项目中动态设置 rc 参数,所有 rc 参数设置都存储在名为 matplotlib.rcParams 的类似于字典的变量中,该变量对于 Matplotlib 软件包是全局的。rcParams 可以直接修改。通过这种方法的修改会对全局产生影响,在 Matplotlib 的其他方法中也可以单独对某个参数进行修改。
%matplotlib inline
from matplotlib import pyplot as plt
# 定义全局字体
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
# 定义X轴刻度颜色
plt.rcParams['xtick.color'] = 'blue'
# 定义线条上点的形状
plt.rcParams['lines.marker'] = 'o'
# 定义图例在左上角
plt.rcParams['legend.loc'] = 'upper left'
x = range(2,26,2)
y = range(0,12)
a = [5,10,15,20,15,30]
b = [3,4,5,6,7,8]
plt.title('这是一个标题')
plt.xlabel('这是X轴标题')
plt.ylabel('这是Y轴标题')
plt.grid(True)
plt.plot(x,y)
plt.plot(a,b)
plt.legend(['图例一','图例二'])
plt.show()
import pandas as pd
from matplotlib import pyplot as plt
# 读取数据
path = r'/Users/davidlin/Desktop/data-coding/data/aiqiyi.xlsx'
movies = pd.read_excel(path,sheet_name='Sheet1')
# 根据上映时间分组
groups_year = movies.groupby('上映时间')
groups_year.groups
# 根据评分取出每年上映的电影数量
movie_count = groups_year['评分'].count()
# 取出索引作为X轴数据
x = movie_count.index.tolist()
# 取出每年的电影数量的值作为Y轴数据
y = movie_count.values.tolist()
# 绘制折线图
plt.plot(x,y,color='green',alpha=0.5,linestyle='-',linewidth=3)
plt.xlabel('Year')
plt.ylabel('Numbers')
plt.title('Nmubers/Year')
plt.show()
%matplotlib inline
import pandas as pd
from matplotlib import pyplot as ply
# 导入数据
path = r'/Users/davidlin/Desktop/data-coding/data/600001SH.xlsx'
stocks = pd.read_excel(path)
print(stocks.shape)
stocks.head()
(105, 13)
代码 | 简称 | 日期 | 前收盘价(元) | 开盘价(元) | 最高价(元) | 最低价(元) | 收盘价(元) | 成交量(股) | 成交金额(元) | 涨跌(元) | 涨跌幅(%) | 均价(元) | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 600004.SH | 白云机场 | 2015-01-04 | 14.23 | 14.28 | 14.28 | 12.81 | 13.04 | 12091206 | 166226459 | -1.19 | -8.3626 | 13.7477 |
1 | 600004.SH | 白云机场 | 2015-01-05 | 13.04 | 12.79 | 13.33 | 12.60 | 13.14 | 17396695 | 227096572 | 0.10 | 0.7669 | 13.0540 |
2 | 600004.SH | 白云机场 | 2015-01-06 | 13.14 | 13.17 | 13.45 | 13.06 | 13.43 | 9676196 | 127728786 | 0.29 | 2.2070 | 13.2003 |
3 | 600004.SH | 白云机场 | 2015-01-07 | 13.43 | 13.23 | 13.23 | 12.35 | 12.42 | 2315000 | 29774567 | -1.01 | -7.5205 | 12.8616 |
4 | 600004.SH | 白云机场 | 2015-01-08 | 12.42 | 12.60 | 12.84 | 12.15 | 12.70 | 18756201 | 235967215 | 0.28 | 2.2544 | 12.5808 |
# 将日期列的值作为X轴
x = stocks['日期'].values.tolist()
# 将开盘价列的值作为Y轴
y = stocks['开盘价(元)'].values.tolist()
# 绘制折线图
plt.plot(x,y)
plt.xlabel('Time')
plt.ylabel('Price')
plt.title('Open/Time')
plt.show()
假设大家在30岁的时候,根据自己的实际情况,统计出来你和你同事各自从11岁到30岁每年交的男/女朋友的数量如列表y1和y2,请在一个图中绘制出该数据的折线图,从而分析每年交朋友的数量走势。
y1 = [1,0,1,1,2,4,3,4,4,5,6,5,4,3,3,1,1,1,1,1]
y2 = [1,0,3,1,2,2,3,4,3,2,1,2,1,1,1,1,1,1,1,1]
%matplotlib inline
from matplotlib import pyplot as plt
from matplotlib import font_manager
# 添加字体
my_font = font_manager.FontProperties(fname=r'C:\Users\lin-a\Desktop\Python数据分析\经典黑体简.TTF')
# X轴数据
x = range(11,31)
# Y轴数据
y1 = [1,0,1,1,2,4,3,4,4,5,6,5,4,3,3,1,1,1,1,1]
y2 = [1,0,3,1,2,2,3,4,3,2,1,2,1,1,1,1,1,1,1,1]
# 设置画布
plt.figure(figsize=(20,8),dpi=80)
# 设置第一条曲线
plt.plot(x,y1,label='我自己')
plt.plot(x,y2,label='我的朋友')
# 设置X轴刻度
xtick_label = ['{}岁'.format(i) for i in x]
plt.xticks(x,xtick_label,fontproperties=my_font,rotation=45)
# 设置图示
plt.legend(prop=my_font)
# 设置标签
plt.xlabel('年龄',fontproperties=my_font)
plt.ylabel('女朋友数量',fontproperties=my_font)
plt.title('年龄与女朋友的相关性',fontproperties=my_font)
# 设置网格
plt.grid(alpha=0.4)
plt.show()
%matplotlib inline
from matplotlib import pyplot as plt
from matplotlib import font_manager
import math
my_font = font_manager.FontProperties(fname=r'C:\Users\lin-a\Desktop\Python数据分析\经典黑体简.TTF')
x = range(0,10)
y1 = [i**2 for i in range(0,10)]
y2 = [i**3 for i in range(0,10)]
y3 = [i**0.5 for i in range(0,10)]
# 设置画布
plt.figure(figsize=(10,8),dpi=80)
# 第一个子图
plt.subplot(2,2,1)
plt.plot(x,y1)
plt.title('数学公式——平方',fontproperties=my_font)
# 第二个子图
plt.subplot(2,2,2)
plt.plot(x,y2)
plt.title('数学公式——立方',fontproperties=my_font)
# 第三个子图
plt.subplot(2,2,3)
plt.plot(x,y3)
plt.title('数学公式——开立方根',fontproperties=my_font)
plt.show()