matplotlib

绘图架构

学习目标

  • 目标
    • 知道Matplotlib的绘图架构
  • 应用

一、什么是Matplotlib

matplotlib

  • 是专门用于开发2D图表(包括3D图表)
  • 使用起来及其简单
  • 以渐进、交互式方式实现数据可视化

二、为什么要学习Matplotlib

可视化是在整个数据挖掘的关键辅助工具,可以清晰的理解数据,从而调整我们的分析方法。

  • 能将数据进行可视化,更直观的呈现
  • 使数据更加客观、更具说服力

例如下面两个图为数字展示和图形展示:

star

我们先来简单画一个图看下效果

plt.figure(figsize=(20, 8), dpi = 100)
plt.plot([1,2,3], [4,5,6])
plt.show()

先看效果1

四、Matplotlib框架构成

matplotlib框架分为三层,这三层构成了一个栈,上层可以调用下层。

三层

1、后端层

matplotlib的底层,实现了大量的抽象接口类,这些API用来在底层实现图形元素的一个个类

  • FigureCanvas对象实现了绘图区域这一概念
  • Renderer对象在FigureCanvas上绘图

2、美工层

图形中所有能看到的元素都属于Artist对象,即标题、轴标签、刻度等组成图形的所有元素都是Artist对象的实例

  • Figure:指整个图形(包括所有的元素,比如标题、线等)
  • Axes(坐标系):数据的绘图区域
  • Axis(坐标轴):坐标系中的一条轴,包含大小限制、刻度和刻度标签

特点为:

  • 一个figure(图)可以包含多个axes(坐标系),但是一个axes只能属于一个figure。
  • 一个axes(坐标系)可以包含多个axis(坐标轴),包含两个即为2d坐标系,3个即为3d坐标系

artist

3、脚本层

主要用于可视化编程,pytplot模块可以提供给我们一个与matplotlib打交道的接口。可以只通过调用pyplot模块的函数从而操作整个程序包,来绘制图形。

  • 操作或者改动Figure对象,例如创建Figure对象
  • 大部分工作是处理样本文件的图形与坐标的生成

折线图与基础绘图功能

学习目标

  • 目标
    • 知道如何解决中文显示问题
    • 知道matplotlib的图结构
    • 应用figure实现创建绘图区域大小
    • 应用plot实现折线图的绘制
    • 应用title,xlabel,ylabel实现标题以及x,y轴名设置
    • 应用xticks,yticks实现axes的刻度设置和标注
    • 应用savefig实现图形的本地保存
    • 应用grid实现显示网格应用axis实现图像形状修改
    • 应用legend实现图形标注信息显示
    • 应用plt.subplots实现多坐标系的创建
    • 知道如何设置多个axes的标题、刻度
    • 知道折线图的应用场景
  • 应用
    • 天气的温度变化显示

一、Parts of a Figure

fig

二、折线图绘制与保存图片

为了更好的去理解所有基础绘图功能,我们通过天气温度变化的绘图来融合所有的基础API使用

1、matplotlib.pyplot模块

matplotlib.pytplot包含了一系列类似于matlab的画图函数。 它的函数作用于当前图形(figure)的当前坐标系(axes)。

import matplotlib.pyplot as plt

2、折线图绘制与显示

展现上海一周的天气,比如从星期一到星期日的天气温度如下

plt.figure(figsize=(10, 10))
plt.plot([1, 2, 3, 4, 5, 6 ,7], [17,17,18,15,11,11,13])
plt.show()

折线图

可以看到这样去显示效果并不好,图形的大小等等,所以我们可以通过加入更多的功能。

3、修改图形大小与图片保存

plt.figure(figsize=(), dpi=)
    figsize:指定图的长宽
    dpi:图像的清晰度
    返回fig对象
plt.savefig(path)
plt.figure(figsize=(20, 8), dpi=80)
plt.savefig("test.png")

会将图片保存到当前路径下

savefig

三、温度变化显示

需求:画出某城市11点到12点1小时内每分钟的温度变化折线图,温度范围在15度~18度

效果:

上海1

1、构造数据、显示

# 画出温度变化图
# 创建一个figure
plt.figure(figsize=(20, 8), dpi=80)

# 准备x, y坐标的数据
x = range(60)
y_shanghai = [random.uniform(15, 18) for i in x]

# 画折线图
plt.plot(x, y_shanghai, label="上海")

plt.show()

上海2

2、自定义x,y刻度以及中文显示

  • plt.xticks(x, **kwargs)

    x:要显示的刻度值

  • plt.yticks(y, **kwargs)

    y:要显示的刻度值

# 增加以下两行代码
# 构造中文列表的字符串
x_ch = ["11点{}分".format(i) for i in x]
y_ticks = range(40)

# 修改x,y坐标的刻度
plt.xticks(x[::5], x_ch[::5])
plt.yticks(y_ticks[::5])

上海3

如果没有解决过中文问题的话,会显示这个样子:

中文问题

2.1 中文显示问题解决

下载中文字体(黑体,看准系统版本)

  • 下载 arial unicode ms 字体到 /home 目录

  • 拷贝字体到 usr/share/fonts 下:

    sudo cp ~/arial unicode ms.ttf /usr/share/fonts/arial unicode ms.ttf
    
  • 修改配置文件matplotlibrc 并且在~/.matplotlib/matplotlibrc也进行修改

    在安装的地方找到虚拟环境ai/lib/python3.6/site-packages/matplotlib/mpl-data目录下面,修改下面三项配置

    font.family         : sans-serif        
    
    font.sans-serif     : arial unicode ms, Bitstream Vera Sans, Lucida Grande, Verdana, Geneva, Lucid, Arial, Helvetica, Avant Garde, sans-serif
    
  • 删除matplotlib字体缓存:

    rm -rf ~/matplotlib/fontList.json
    

3、增加标题、x轴y轴描述信息

plt.xlabel("时间")
plt.ylabel("温度")
plt.title("中午11点0分到12点之间的温度变化图示")

上海4

4、再添加一个城市的温度变化

收集到北京当天温度变化情况,温度在1度到3度。怎么去添加另一个在同一坐标系当中的不同图形,其实很简单只需要再次plot即可,但是需要区分线条,如下显示

上海1

# 生成北京的温度
y_beijing = [random.uniform(1, 3) for i in x]

# 画折线图
plt.plot(x, y_shanghai, label="上海")
# 使用plot可以多次画多个折线
plt.plot(x, y_beijing, color='r', linestyle='--', label="北京")

# 添加图形注释
plt.legend(loc="best")

我们仔细观察,用到了两个新的地方,一个是对于不同的折线展示效果,一个是添加注释

4.1自定一个图形风格

颜色字符风格字符
r 红色 - 实线
g 绿色 - - 虚线
b 蓝色 -. 点划线
w 白色 : 点虚线
c 青色 ' ' 留空、空格
m 洋红  
y 黄色  
k 黑色

4.2添加注释

plt.legend(loc="best")

legend

5、多个坐标系显示-plt.subplots

如果我们想要将上海和北京的天气图显示在同一个图的不同坐标系当中,效果如下:

subplots

可以通过subplots函数实现(旧的版本中有subplot,使用起来不方便),推荐subplots函数

  • matplotlib.pyplot.subplots(nrows=1, ncols=1, **fig_kw) 创建一个带有多个坐标系的图

    Parameters:    
    
    nrows, ncols : int, optional, default: 1, Number of rows/columns of the subplot grid.
    **fig_kw : All additional keyword arguments are passed to the figure() call.
    
    Returns:    
    fig : 图对象
    ax : 
        设置标题等方法不同:
        set_xticks
        set_yticks
        set_xlabel
        set_ylabel
    

    关于axes子坐标系的更多方法:参考https://matplotlib.org/api/axes_api.html#matplotlib.axes.Axes

# 画出温度变化图,展现在不同axes里面
# 创建一个figure
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(20, 8), dpi=80)

# 准备x, y坐标的数据
x = range(60)
# y的刻度范围
y_ticks = range(40)
y_shanghai = [random.uniform(15, 18) for i in x]

# 生成北京的温度
y_beijing = [random.uniform(1, 3) for i in x]

# 构造中文列表的字符串
x_ch = ["11点{}分".format(i) for i in x]

# 画折线图
axes[0].plot(x, y_shanghai, label="上海")
# 使用plot可以多次画多个折线
axes[1].plot(x, y_beijing, color='r', linestyle='--', label="北京")


# 美化x,y的刻度值
# 第一个参数必须是刻度数字类型,第二个是对应着第一个数字的中文描述
axes[0].set_xticks(x[::5], x_ch[::5])
axes[0].set_yticks(y_ticks[::5])

axes[1].set_xticks(x[::5], x_ch[::5])
axes[1].set_yticks(y_ticks[::5])

# 增加x,y描述信息和标题信息
axes[0].set_xlabel("时间")
axes[0].set_ylabel("温度")

axes[1].set_xlabel("时间")
axes[1].set_ylabel("温度")

axes[0].set_title("中午11点0分到12点之间的温度变化图示")
axes[1].set_title("中午11点0分到12点之间的温度变化图示")

axes[0].legend(loc="best")
axes[1].legend(loc="best")

plt.show()

四、折线图的应用场景

  • 呈现公司产品(不同区域)每天活跃用户数
  • 呈现app每天下载数量
  • 呈现产品新功能上线后,用户点击次数随时间的变化

小结

开头的这几个目标应用全都很重要

  • 知道如何解决中文显示问题
  • 知道matplotlib的图结构
  • 应用figure实现创建绘图区域大小
  • 应用plot实现折线图的绘制
  • 应用title,xlabel,ylabel实现标题以及x,y轴名设置
  • 应用xticks,yticks实现axes的刻度设置和标注
  • 应用savefig实现图形的本地保存
  • 应用grid实现显示网格应用axis实现图像形状修改
  • 应用legend实现图形标注信息显示
  • 应用plt.subplots实现多坐标系的创建
  • 知道如何设置多个axes的标题、刻度

柱状图

学习目标

  • 目标
    • 应用bar实现柱状图的绘制
    • 知道柱状图的应用场景
  • 应用
    • 电影票房收入绘制

matplotlib能够绘制折线图、柱状图、饼图、直方图、散点图、热力图、K线图等,但是,我们需要知道不同的统计图到底能够表示出什么,以此来决定选择哪种统计图来更直观的呈现我们的数据

一、常见图形种类及意义

图形种类

  • 折线图:以折线的上升或下降来表示统计数量的增减变化的统计图

    特点:能够显示数据的变化趋势,反映事物的变化情况。(变化)

  • 直方图:由一系列高度不等的纵向条纹或线段表示数据分布的情况。 一般用横轴表示数据范围,纵轴表示分布情况。

    特点:绘制,连续性的数据展示一组或者多组数据的分布状况(统计)

  • 柱状图:排列在工作表的列或行中的数据可以绘制到柱状图中。

    特点:绘制连离散的数据,能够一眼看出各个数据的大小,比较数据之间的差别。(统计)

  • 散点图:用两组数据构成多个坐标点,考察坐标点的分布,判断两变量之间是否存在某种关联或总结坐标点的分布模式。

    特点:判断变量之间是否存在数量关联趋势,展示离群点(分布规律)

二、柱状图图绘制

柱状图

需求:每部电影的票房收入对比?

1、画出每部电影的票房收入对比,效果如下:

电影票房条形图

电影数据如下图所示:

电影票房数据

['雷神3:诸神黄昏','正义联盟','东方快车谋杀案','寻梦环游记','全球风暴', '降魔传','追捕','七十七天','密战','狂兽','其它']
[73853,57767,22354,15969,14839,8725,8716,8318,7916,6764,52222]

2、绘制

  • matplotlib.pyplot.bar(x, width, align='center', **kwargs)

绘制柱状图


Parameters:    
x : sequence of scalars.

width : scalar or array-like, optional
柱状图的宽度

align : {‘center’, ‘edge’}, optional, default: ‘center’
Alignment of the bars to the x coordinates:
‘center’: Center the base on the x positions.
‘edge’: Align the left edges of the bars with the x positions.
每个柱状图的位置对齐方式

**kwargs :
color:选择柱状图的颜色

Returns:    
`.BarContainer`
Container with all the bars and optionally errorbars.

代码:

# 完成简单的条形图展现不同的电影票房之间的对比
plt.figure(figsize=(20, 8), dpi=80)

# 准备电影的名字以及电影的票房数据
movie_name = ['雷神3:诸神黄昏','正义联盟','东方快车谋杀案','寻梦环游记','全球风暴','降魔传','追捕','七十七天','密战','狂兽','其它']
y = [73853,57767,22354,15969,14839,8725,8716,8318,7916,6764,52222]
# 放进横坐标的数字列表
x = range(len(movie_name))

# 画出条形图
plt.bar(x, y, width=0.5, color=['b','r','g','y','c','m','y','k','c','g','g'])

# 修改刻度名称
plt.xticks(x, movie_name)

plt.show()

如何对比电影票房收入才更能加有说服力?

3、比较相同天数的票房

有时候为了公平起见,我们需要对比不同电影首日和首周的票房

3.1数据如下

movie_name = ['雷神3:诸神黄昏','正义联盟','寻梦环游记']

first_day = [10587.6,10062.5,1275.7]
first_weekend=[36224.9,34479.6,11830]

数据来源: https://piaofang.maoyan.com/?ver=normal

效果如下:

首日首周票房对比

3.2 分析

  • 添加首日首周两部分的柱状图
  • x轴中文坐标位置调整

代码:

# 三部电影的首日和首周票房对比
plt.figure(figsize=(20, 8), dpi=80)

movie_name = ['雷神3:诸神黄昏','正义联盟','寻梦环游记']

first_day = [10587.6,10062.5,1275.7]
first_weekend=[36224.9,34479.6,11830]

x = range(len(movie_name))

# 画出柱状图
plt.bar(x, first_day, width=0.2, label="首日票房")
# 首周柱状图显示的位置在首日的位置右边
plt.bar([i+0.2 for i in x], first_weekend, width=0.2, label="首周票房")

# 显示X轴中文,固定在首日和首周的中间位置
plt.xticks([i+0.1 for i in x], movie_name)
plt.legend(loc='best')

plt.show()

三、柱状图应用场景

适合用在分类数据对比场景上

  • 数量统计
  • 用户数量对比分析

直方图

学习目标

  • 目标
    • 应用hist实现直方图的绘制
    • 知道直方图图的应用场景
  • 应用

    电影时长分布

一、直方图(Histogram)介绍

直方图,形状类似柱状图却有着与柱状图完全不同的含义。直方图牵涉统计学的概念,首先要对数据进行分组,然后统计每个分组内数据元的数量。 在坐标系中,横轴标出每个组的端点,纵轴表示频数,每个矩形的高代表对应的频数,称这样的统计图为频数分布直方图。

相关概念:

  • 组数:在统计数据时,我们把数据按照不同的范围分成几个组,分成的组的个数称为组数
  • 组距:每一组两个端点的差

直方图

二、电影时长分布绘制

现有250部电影的时长,希望统计出这些电影时长的分布状态(比如时长为100分钟到120分钟电影的数量,出现的频率)等信息,你应该如何呈现这些数据?

数据:

time =[131,  98, 125, 131, 124, 139, 131, 117, 128, 108, 135, 138, 131, 102, 107, 114, 119, 128, 121, 142, 127, 130, 124, 101, 110, 116, 117, 110, 128, 128, 115,  99, 136, 126, 134,  95, 138, 117, 111,78, 132, 124, 113, 150, 110, 117,  86,  95, 144, 105, 126, 130,126, 130, 126, 116, 123, 106, 112, 138, 123,  86, 101,  99, 136,123, 117, 119, 105, 137, 123, 128, 125, 104, 109, 134, 125, 127,105, 120, 107, 129, 116, 108, 132, 103, 136, 118, 102, 120, 114,105, 115, 132, 145, 119, 121, 112, 139, 125, 138, 109, 132, 134,156, 106, 117, 127, 144, 139, 139, 119, 140,  83, 110, 102,123,107, 143, 115, 136, 118, 139, 123, 112, 118, 125, 109, 119, 133,112, 114, 122, 109, 106, 123, 116, 131, 127, 115, 118, 112, 135,115, 146, 137, 116, 103, 144,  83, 123, 111, 110, 111, 100, 154,136, 100, 118, 119, 133, 134, 106, 129, 126, 110, 111, 109, 141,120, 117, 106, 149, 122, 122, 110, 118, 127, 121, 114, 125, 126,114, 140, 103, 130, 141, 117, 106, 114, 121, 114, 133, 137,  92,121, 112, 146,  97, 137, 105,  98, 117, 112,  81,  97, 139, 113,134, 106, 144, 110, 137, 137, 111, 104, 117, 100, 111, 101, 110,105, 129, 137, 112, 120, 113, 133, 112,  83,  94, 146, 133, 101,131, 116, 111,  84, 137, 115, 122, 106, 144, 109, 123, 116, 111,111, 133, 150]

效果:

电影时长分布

1、matplotlib.pyplot.hist(x, bins=None, normed=None, **kwargs)

直方图绘制

Parameters:    
x : (n,) array or sequence of (n,) arrays

bins : integer or sequence or ‘auto’, optional
组距

normed : bool, optional
以频率显示或者以頻数显示,默认頻数,值1为频率

2、分析

  • 设置组距
  • 设置组数(通常对于数据较少的情况,分为5~12组,数据较多,更换图形显示方式)
    • 通常设置组数会有相应公式:组数 = 极差/组距= (max-min)/bins

代码:

# 展现不同电影的时长分布状态
plt.figure(figsize=(20, 8), dpi=100)

# 准备时长数据
time =[131,  98, 125, 131, 124, 139, 131, 117, 128, 108, 135, 138, 131, 102, 107, 114, 119, 128, 121, 142, 127, 130, 124, 101, 110, 116, 117, 110, 128, 128, 115,  99, 136, 126, 134,  95, 138, 117, 111,78, 132, 124, 113, 150, 110, 117,  86,  95, 144, 105, 126, 130,126, 130, 126, 116, 123, 106, 112, 138, 123,  86, 101,  99, 136,123, 117, 119, 105, 137, 123, 128, 125, 104, 109, 134, 125, 127,105, 120, 107, 129, 116, 108, 132, 103, 136, 118, 102, 120, 114,105, 115, 132, 145, 119, 121, 112, 139, 125, 138, 109, 132, 134,156, 106, 117, 127, 144, 139, 139, 119, 140,  83, 110, 102,123,107, 143, 115, 136, 118, 139, 123, 112, 118, 125, 109, 119, 133,112, 114, 122, 109, 106, 123, 116, 131, 127, 115, 118, 112, 135,115, 146, 137, 116, 103, 144,  83, 123, 111, 110, 111, 100, 154,136, 100, 118, 119, 133, 134, 106, 129, 126, 110, 111, 109, 141,120, 117, 106, 149, 122, 122, 110, 118, 127, 121, 114, 125, 126,114, 140, 103, 130, 141, 117, 106, 114, 121, 114, 133, 137,  92,121, 112, 146,  97, 137, 105,  98, 117, 112,  81,  97, 139, 113,134, 106, 144, 110, 137, 137, 111, 104, 117, 100, 111, 101, 110,105, 129, 137, 112, 120, 113, 133, 112,  83,  94, 146, 133, 101,131, 116, 111,  84, 137, 115, 122, 106, 144, 109, 123, 116, 111,111, 133, 150]
# 定义一个间隔大小
a = 2

# 得出组数
bins = int((max(time) - min(time)) / a)

# 画出直方图
plt.hist(time, bins, normed=1)

# 指定刻度的范围,以及步长
plt.xticks(list(range(min(time), max(time)))[::2])

plt.xlabel("电影时长大小")
plt.ylabel("电影的数据量")

plt.show()

电影时长分布无网格

3、增加网格显示

为了更好将图形对应到

plt.grid(True, linestyle='--', alpha=0.5)

三、直方图的场景

  • 用于表示分布情况
  • 通过直方图还可以观察和估计哪些数据比较集中,异常或者孤立的数据分布在何处

例如:用户年龄分布,商品价格分布

四、直方图与其他图表的对比

  • 柱状图是以矩形的长度表示每一组的频数或数量,其宽度(表示类别)则是固定的,利于较小的数据集分析。
  • 直方图是以矩形的长度表示每一组的频数或数量,宽度则表示各组的组距,因此其高度与宽度均有意义,利于展示大量数据集的统计结果。
  • 由于分组数据具有连续性,直方图的各矩形通常是连续排列,而柱状图则是分开排列。

饼图

学习目标

  • 目标
    • 应用hist实现直方图的绘制
    • 知道直方图图的应用场景
  • 应用
    • 电影时长分布

一、饼图(Pie)介绍

饼图广泛得应用在各个领域,用于表示不同分类的占比情况,通过弧度大小来对比各种分类。饼图通过将一个圆饼按照分类的占比划分成多个区块,整个圆饼代表数据的总量,每个区块(圆弧)表示该分类占总体的比例大小,所有区块(圆弧)的加和等于 100%。

饼图

二、饼图绘制

1、如果需要显示不同的电影的排片占比

1.1电影排片:

电影排片

1.2数据:

movie_name = ['雷神3:诸神黄昏','正义联盟','东方快车谋杀案','寻梦环游记','全球风暴','降魔传','追捕','七十七天','密战','狂兽','其它']

place_count = [60605,54546,45819,28243,13270,9945,7679,6799,6101,4621,20105]

1.3效果

电影排片占比显示

3、分析

  • 注意显示的百分比的位数
  • plt.pie(x, labels=,autopct=,colors)
    • x:数量,自动算百分比
    • labels:每部分名称
    • autopct:占比显示指定%1.2f%%
    • colors:每部分颜色

代码

# 展现每部电影的排片的占比
plt.figure(figsize=(20, 8), dpi=100)

# 准备每部电影的名字,电影的排片场次
movie_name = ['雷神3:诸神黄昏','正义联盟','东方快车谋杀案','寻梦环游记','全球风暴','降魔传','追捕','七十七天','密战','狂兽','其它']

place_count = [60605,54546,45819,28243,13270,9945,7679,6799,6101,4621,20105]

# 通过pie
plt.pie(place_count, labels=movie_name, autopct='%1.2f%%', colors=['b','r','g','y','c','m','y','k','c','g','g'])

# 指定显示的pie是正圆
plt.axis('equal')

plt.legend(loc='best')

plt.title("排片占比示意图")
plt.show()

排片占比

4、添加axis

为了让显示的饼图保持圆形,需要添加axis保证长宽一样

plt.axis('equal')

三、饼图应用场景

  • 分类的占比情况(不超过9个分类)

例如:班级男女分布占比,公司销售额占比

其它功能

学习目标

  • 目标
    • 知道annotate或者text添加图的注释
    • 知道animation实现动画的创建
  • 应用

一、使用annotate和text添加图的注释

fig, ax = plt.subplots(nrows=1, ncols=1, dpi=80)

# 使用splines以及设置颜色,将上方和右方的坐标去除
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')

# 将刻度设置为空,去除刻度
plt.xticks([])
plt.yticks([])

# x,y数据
data = np.ones(100)
data[70:] = list(range(1, 31))
print(data)

# 使用annptate添加注释
plt.annotate(
    '这是一个拐点',
    xy=(70, 1), # 箭头指向位置
    arrowprops=dict(arrowstyle='->'),#自定义箭头样式 
    xytext=(50, 10))# 文本位置

plt.plot(data)

plt.xlabel('1')
plt.ylabel('2')
ax.text(
    30, 2,# 文本位置
    '这是一段文本')

效果:

图形添加文本

二、使用animation实现动画

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

fig, ax = plt.subplots()

# 设置x,y数据,显示到图形当中
x = np.arange(0, 2*np.pi, 0.01)
line, = ax.plot(x, np.sin(x))


def init():
    """
    初始设置
    """
    line.set_ydata([np.nan] * len(x))
    return line,


def animate(i):
    """
    更新坐标点函数
    """
    line.set_ydata(np.sin(x + i / 100))
    return line,


ani = animation.FuncAnimation(
    fig, animate, init_func=init, interval=2, blit=True, save_count=50)

plt.show()

三、更多画图功能

请参考:https://matplotlib.org/tutorials/index.html

原文地址:https://www.cnblogs.com/whigym/p/10485923.html