Matplotlib可视化入门,看这一篇就够了

Matplotlib是 Python 最著名的2D绘图库,提供了丰富的数据绘图工具,主要用于绘制一些统计图形。Matplotlib可用于Python脚本,Python和IPython shell,Jupyter笔记本,Web应用程序服务器和四个图形用户界面工具包。

matplotlib.pyplot API 官方教程

高效使用 Python 可视化工具 Matplotlib

相信初接触matplotlib肯定会有些困惑,同样一个目标有多个解决方案,有人用plt.xx,有人用ax.xx,对小白及其不友好,照葫芦画瓢搞出来了,但不明白为什么,写出来的代码很混乱。下次遇到问题依然一头雾水。我也是这样,所以,花时间读了很多文章,整理了一下知识点,入门够用了。另,涉及到的文章都贴出了链接,可以一并阅读,加深理解。

matplotlib架构

matplotlib的架构分为以下三层

  • Scripting (脚本)层
  • Artist (表现)层。拥有许多可视化元素,如figure、axes、axis等元素。
  • Backend (后端)层。包含 pyplot 和 pylab 模块(已弃用,不推荐)

它们之间的访问关系是:

Scripting 访问 Artist, Artist 访问 Backend

理论上各层都可以画出相同的图形,但越底层的操作越细节越困难,越高层越易于人机交互,越容易。也就是说上层是下层的封装,把一些不需要打交道的事情封装好,实际画图只关心效果即可。

matplotlib 架构

matplotlib两种绘图API

在Matplotlib库中提供了两种风格的API供开发者使用。这也就是为什么有人用plt.xx,有人用ax.xx的原因。好的代码应该坚持使用一种风格,否则会显得混乱,阅读起来困难,不利于维护。

  • Pyplot编程接口(state-based)不推荐
  • 面向对象的编程接口(object-based)推荐

之前有三种api,还有一种pylab api,模仿matlab的工作方式,但大量导入全局命名方式导致意外行为,被认为是糟糕的风格,matplotlib最新版中已弃用此方式。理解matplotlib、pylab与pyplot之间的关系

另外,pandas自带的df.plot()方法也可以绘制简单的图形,它是使用matplotlib库的plot()方法的简单包装实现的。最好不要用,pandas作为数据分析来用,绘图就交给matplotlib等专业的绘图库来做。下文也介绍一下,下次看到这种解决方案可以心中有数,不迷惑。

Matplotlib中的两种绘图API说明

matplotlib 实际上就是提供了 3 种API

Matplotlib中的plt和ax都是啥?

matplotlib:先搞明白plt. /ax./ fig再画

matplotlib图像的结构

matplotlib_PartsOfAFugure_2021_01_16

在matplotlib中,整个图像为一个Figure对象,相当于画板。在Figure对象中可以包含一个或者多个Axes对象(画纸)。每个Axes(ax)对象都是一个拥有自己坐标系统axis的绘图区域。

Python matplotlib结构详解

以两个例子来介绍两种方法的使用。下面两幅图分别用pyplot编程接口和面向对象编程接口实现。单子图、多子图都涉及到了,用法在代码里表达的很清楚了。

单子图柱状图

matplotlib_两种绘图api比较示例_单子图_2021_01_18

多子图柱状图

matplotlib_两种绘图api比较示例_多子图_2021_01_18

一些其他图形如折线图、散点图、饼图等跟示例的柱状图大同小异,各种参数自行学习。不容错过的Matplotlib常见用法小结 非常全面的Matplotlib画图方法、Matplotlib 1.4W+字教程的图形绘制部分

  • plot 折线图
  • bar 柱状图
  • barh 条形图
  • hist 直方图
  • pie 饼图
  • boxplot 箱形图
  • scatter 散点图
  • polar 极坐标图

Pyplot编程接口(state-based)不推荐

Pyplot封装了底层的绘图函数提供了一种绘图环境,当使用plt.xx绘制图形的时候,默认的Figure以及Axes等对象会自动创建以支持图形的绘制。此方式屏蔽了一些底层通用的绘图对象的创建细节,书写简洁。另外,pyplot是有状态的,亦即它会保存当前图片和作图区域的状态,新的作图函数会作用在当前图片的状态基础之上,代码的位置要注意。遇到一些比较复杂的图时不方便。官方推荐使用面向对象方式绘图。

import numpy as np
import matplotlib.pyplot as plt
 
# 准备数据
dog = (20, 28, 22, 30)
cat = (25, 32, 20, 27)

ind = np.arange(len(dog)) # 生成0-3的数组,用于x轴刻度值
quarter = ['一季度','二季度','三季度','四季度']
width = 0.35    # 图形柱的宽度

#################################################
# 一个子图

# 绘图
# x的位置调节好,不然两个柱会重叠
plt.bar(ind - width/2, dog, width, label='Dog')
plt.bar(ind + width/2, cat, width, label='Cat')

# 调节组件
plt.ylabel('销售额(万)')
plt.title('各季度猫狗产业销售额')
plt.xticks(ind,quarter)
plt.legend(loc=2)

# 保存图形
plt.savefig('matplotlib_pyplot方式单子图.png')
#################################################

#################################################
# 多个子图。有状态,细节调整需在各个subplot内调节

# 绘图 第一个子图
plt.subplot(121)    #1行2列,占用第一个
plt.bar(ind, dog, width, color='dodgerblue', label='Dog')

# 调节组件
plt.ylabel('销售额(万)')
plt.title('各季度狗产业销售额')
plt.xticks(ind,quarter)

# 绘图 第二个子图
plt.subplot(122)    #1行2列,占用第二个
plt.bar(ind, cat, width, color='darkorange', label='Cat')

# 调节组件
plt.ylabel('销售额(万)')
plt.title('各季度猫产业销售额')
plt.xticks(ind,quarter)

# 保存图形
plt.savefig('matplotlib_pyplot方式多子图.png')
#################################################

# 交互展示
plt.show()

面向对象的编程接口(object-based)推荐

面向对象的绘图方式主要使用matplotlib的两个子类:matplotlib.figure.Figure和matplotlib.axes.Axes。我们需要自己创建figure(画板),axes(画纸)。画板(figure)为matplotlib.figure.Figure的一个实例,每个子图(画纸,axes)为matplotlib.axes.Axes的一个实例,分别可以继承父类的所有方法,也就是说你绘图时,你想设置的元素(网格线啊,坐标刻度啊等)都可以在二者的属性中找出来使用。使用面向对象编程接口有利于我们对于图形绘制的完整控制,处理复杂图形更有优势。但是相对于Pyplot接口可能需要书写更多的代码。

import numpy as np
import matplotlib.pyplot as plt

# 准备数据
dog = (20, 28, 22, 30)
cat = (25, 32, 20, 27)

ind = np.arange(len(dog)) # 生成0-3的数组,用于x轴刻度值
quarter = ['一季度','二季度','三季度','四季度']
width = 0.35    # 图形柱的宽度

#################################################
# 一个子图

# 绘图
fig, ax = plt.subplots()    # 实例画板fig画纸ax
# x的位置调节好,不然两个柱会重叠
ax.bar(ind - width/2, dog, width, label='Dog')
ax.bar(ind + width/2, cat, width, label='Cat')

# 调节组件
ax.set_ylabel('销售额(万)')
ax.set_title('各季度猫狗产业销售额')
ax.set_xticks(ind)
ax.set_xticklabels(quarter)
ax.legend(loc=2)

# 保存图形
fig.savefig('matplotlib_两种绘图api比较示例_单子图.png')
#################################################

#################################################
# 多个子图。无状态,ax[0],ax[1]代表各子图

# 绘图
fig, ax = plt.subplots(1,2) #(1,2)代表1行2列两个区域
# 设置图形对象 :窗口

# ax[0]代表第一个子图,ax[1]代表第二个子图
ax[0].bar(ind, dog, width, color='dodgerblue', label='Dog')
ax[1].bar(ind, cat, width, color='darkorange', label='Cat')

# 调节组件
ax[0].set_ylabel('销售额(万)')
ax[0].set_title('各季度狗产业销售额')
ax[0].set_xticks(ind)
ax[0].set_xticklabels(quarter)

ax[1].set_ylabel('销售额(万)')
ax[1].set_title('各季度猫产业销售额')
ax[1].set_xticks(ind)
ax[1].set_xticklabels(quarter)

# 保存图形
fig.savefig('matplotlib_两种绘图api比较示例_多子图.png')
#################################################

# 交互展示
plt.show()  # 面向对象接口不能使用交互式的show()方法对图像直接进行显示。如果想交互显示,需要用pyplot方式

pandas自带df.plot()方法 不要用

pandas自带的df.plot()方法也可以绘制简单的图形,它是使用matplotlib库的plot()方法的简单包装实现的。最好不要用,pandas作为数据分析来用,绘图就交给matplotlib等专业的绘图库来做。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# 准备数据
dog = (20, 28, 22, 30)
cat = (25, 32, 20, 27)
data = {
        'Dog': dog,
        'Cat': cat}

ind = np.arange(len(dog)) # 生成0-3的数组,用于x轴刻度值
quarter = ['一季度','二季度','三季度','四季度']
width = 0.35    # 图形柱的宽度

# 生成DataFrame
df = pd.DataFrame(data,index=ind)

# df.plot()方法绘图。kind代表绘图类型
ax = df.plot(kind='bar')

# 调节组件
ax.set_ylabel('销售额(万)')
ax.set_title('各季度猫狗产业销售额')
ax.set_xticks(ind)
ax.set_xticklabels(quarter)
ax.legend(loc=2)

# 交互展示
plt.show()
matplotlib_两种绘图api比较示例_单子图_2021_01_18

Pandas的可视化操作(利用pandas得到图表)

matplotlib组件详解

在matplotlib中,整个图像为一个Figure对象。在Figure对象中可以包含一个或者多个Axes对象。每个Axes(ax)对象都是一个拥有自己坐标系统的绘图区域。

matplotlib的图的构成元素

matplotlib_AnatomyOfAFigure_2021_01_16
  • 坐标轴(axis)
  • 坐标轴名称(axis label)
  • 坐标轴刻度(tick)
  • 坐标轴刻度标签(tick label)
  • 坐标轴边界(lim)
  • 网格线(grid)
  • 图例(legend)
  • 标题(title)
  • 边框(spine)

建议收藏!Matplotlib常见组件设置整理

中文乱码、负号显示

知乎问题-中文乱码、负号不能正常显示。看猴子的回答

设置标题 ax.set_title()

单子图用ax.,多子图用ax[].

ax.set_title('标题',fontdict={'size':16},loc = 'left')    #设置16px的字体大小,将标题显示在左侧

设置边框(spine) ax.spines

默认图表中会显示上下左右四条spine,可根据需要设置为不显示

ax.spines['right'].set_visible(False)   #去除右边的spines
ax.spines['bottom'].set_color('r')  #设置底部的spines为红色

设置坐标轴相关

设置坐标轴名称
ax.set_xlabel('季度',fontsize=16)
ax.set_xlabel('销售额',fontsize=16)
设置坐标轴刻度标签
# 更改刻度标签。此例将0,1,2,3更改为一季度,二季度,三季度,四季度
ax.set_xticks(ind)
ax.set_xticklabels(quarter)

# 设置刻度标签属性
# axis : 可选{‘x’, ‘y’, ‘both’} ,选择对哪个轴操作,默认是’both’
# labelsize设置刻度标签的大小
# direction{‘in’, ‘out’, ‘inout’}刻度线的方向
# color : 刻度线的颜色
# labelcolor : 刻度值颜色
ax.tick_params(axis = 'y', labelsize=14,direction='in',labelcolor='r')

ax.tick_params()参数详解

设置刻度间隔
#从pyplot导入MultipleLocator类,这个类用于设置刻度间隔
from matplotlib.pyplot import MultipleLocator

#把x轴的刻度间隔设置为1,并存在变量里
x_major_locator=MultipleLocator(1)

#把y轴的刻度间隔设置为10,并存在变量里
y_major_locator=MultipleLocator(10)

#把x轴的主刻度设置为1的倍数
ax.xaxis.set_major_locator(x_major_locator)

#把y轴的主刻度设置为10的倍数
ax.yaxis.set_major_locator(y_major_locator)
设置坐标轴边界
ax.set_xlim([0,12])  # x轴边界
ax.set_ylim([0,50])  # y轴边界

设置图例 ax.legend()

图例是对图形所展示的内容的解释,比如在一张图中画了三条线,那么这三条线都代表了什么呢?这时就需要做点注释。

两种方式设置图例

# 第一种
# 绘图的时候加上label,之后调用ax.legend()
ax.bar(ind - width/2, dog, width, label='Dog')
ax.bar(ind + width/2, cat, width, label='Cat')
ax.legend()

# 第二种
# 使用ax.legend()按顺序设置好图例
ax.bar(ind - width/2, dog, width)
ax.bar(ind + width/2, cat, width)
ax.legend(['Dog','Cat'])
图例位置

loc参数用来规定图例的位置

如:将图例放在左上角:ax.legend(loc=2)

图例各位置如下

  • 0: ‘best'
  • 1: ‘upper right'
  • 2: ‘upper left'
  • 3: ‘lower left'
  • 4: ‘lower right'
  • 5: ‘right'
  • 6: ‘center left'
  • 7: ‘center right'
  • 8: ‘lower center'
  • 9: ‘upper center'
  • 10: ‘center'

设置网格线 ax.grid()

网格线多用于辅助查看具体的数值大小,横纵坐标都可以设置相应的网格线,视具体情况而论。

# b参数设置是否显示网格
# linestyle:线型
# color:颜色
# linewidth:宽度
# axis:x,y,both,显示x/y/两者的格网。默认both
ax.grid(b = True, linestyle = "--",color = "gray", linewidth = "0.5",axis = 'y') 

设置背景颜色

设置整个图像背景颜色

fig.set_facecolor('white')

设置某个子图背景颜色

ax.set_facecolor('white')

保存图像 fig.savefig

保存图像的时候可以设置分辨率

fig.savefig('xxx.png',dpi=300)

交互展示 ax.show()

显示最终绘制的图像

ax.show()
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容