理解matplotlib绘图
matplotlib是基于Python语言的开源项目,旨在为Python提供一个数据绘图包。Matplotlib 可能是 Python 2D-绘图领域使用最广泛的套件。它能让使用者很轻松地将数据图形化,并且提供多样化的输出格式。
matplotlib使用numpy进行数组运算,并调用一系列其他的Python库来实现硬件交互。matplotlib的核心是一套由对象构成的绘图API。
你需要安装Python, numpy和matplotlib。(可以到python.org下载Python编译器。相关Python包的安装,请参看我的Python小技巧)
matplotlib的官网是: http://matplotlib.org/ 官网有丰富的图例和文档说明。
matplotlib在github的地址为:https://github.com/matplotlib 欢迎有兴趣的开发者fork。
matplotlib是受MATLAB的启发构建的,模仿MATLAB但是不模仿“收费”
1 一个简单的例子
(1) 绘图,画一条直线
import matplotlib.pyplot as plt plt.plot([0, 1], [0, 1]) # plot a line from (0, 0) to (1, 1)
plt.title("a strait line")
plt.xlabel("x value")
plt.ylabel("y value")
plt.savefig("demo.jpg")
plt.show()
(2) 解析
上面的代码实际上封装了很多,如果我们想简单的快速绘图,那么你只要简单的调用上面的代码。但是作为程序员,怎么能甘心做个调用者,让我们解开matplotlib的核心面纱吧
第一行,plt.plot([0,1],[0,1])源码
# 源码1
def plot(*args, **kwargs):
ax = gca() #(1) 获得axes
# allow callers to override the hold state by passing hold=True|False
washold = ax.ishold()
hold = kwargs.pop('hold', None)
if hold is not None:
ax.hold(hold)
try:
ret = ax.plot(*args, **kwargs) #(2) 调用ax.plot()
draw_if_interactive()
finally:
ax.hold(washold) return ret
我们看到里面代码(1) 处调用了gca,当获得了axes之后,plot是通过ax进行的,代码(2)
好的,那么继续深入ax=gca(),查看gca()的源码
# 源码2
def gca(**kwargs):
"""
Get the current :class:`~matplotlib.axes.Axes` instance on the
current figure matching the given keyword args, or create one. If the current axes doesn't exist, or isn't a polar one, the appropriate
axes will be created and then returned. """
ax = gcf().gca(**kwargs)
return ax
好吧,实际上里面还有洞天,继续追踪gcf()的源码
#源码 3
def gcf():
"Get a reference to the current figure." figManager = _pylab_helpers.Gcf.get_active() #(1) 从figure的active 列表中取出最后面的一个,如果列表为空,则返回None
if figManager is not None:
return figManager.canvas.figure #(2) 直接返回当前active figure列表中最上面的那个figure
else:
return figure() #(3) 如果没有则创建一个
在这里获得一个figure,如果程序里面有多个figure,则返回正激活的那个(激活是指如果有多个窗口,则是最上面的那个,这个窗口接触鼠标、键盘输入),如果没有则创建。创建的时候默认就将这个figure设为激活的figure。
OK,回溯到源码2。也就是这个gca()是调用figure的gca(),那么继续探索之旅。
#源码4 figure类的gca
def gca(self, **kwargs):
"""
Get the current axes, creating one if necessary The following kwargs are supported for ensuring the returned axes
adheres to the given projection etc., and for axes creation if
the active axes does not exist: %(Axes)s """
ckey, cax = self._axstack.current_key_axes() #(1) 粗糙axes的是stack
# if there exists an axes on the stack see if it maches
# the desired axes configuration
if cax is not None: # if no kwargs are given just return the current axes
# this is a convenience for gca() on axes such as polar etc.
if not kwargs:
return cax # if the user has specified particular projection detail
# then build up a key which can represent this
else:
# we don't want to modify the original kwargs
# so take a copy so that we can do what we like to it
kwargs_copy = kwargs.copy()
projection_class, _, key = process_projection_requirements(
self, **kwargs_copy) # let the returned axes have any gridspec by removing it from
# the key
ckey = ckey[1:]
key = key[1:] # if the cax matches this key then return the axes, otherwise
# continue and a new axes will be created
if key == ckey and isinstance(cax, projection_class):
return cax # no axes found, so create one which spans the figure
return self.add_subplot(1, 1, 1, **kwargs)
这里和上面gcf类似,也是看是否有已经存在的,如果存在axes,则直接调用,如果不存在,则是通过figure.add_subplot(1,1,1)创建一个axes。
好了,到这边为止,我们通过查看源码已经深入的接触了figure,axes。实际简单的一句plt.plot() 是通过figure上得axes调用plot()实现的。
因此我们可以自己写
fig1 = plt.figure('fig1') #获得一个figure, 这个figure是接下来所有画在这上面对象的载体。可以理解为边框
fig1_axes_1 = fig1.add_axes([0.1, 0.1, 0.8, 0.8])
fig1_axes_1.plot([0,1],[0,1])
2 理清关系
接下来的内容很多转载自http://www.cnblogs.com/vamei/archive/2013/01/30/2879700.html
我们将上面的直线绘图更改为面向对象式(OO, object-oriented)的,为此,我们引入两个类: Figure和FigureCanvas。(函数式编程也调用了这些类,只是调用的过程被函数调用所遮掩。)
# object-oriented plot from matplotlib.figure import Figure
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas fig = Figure()
canvas = FigureCanvas(fig)
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8]) line, = ax.plot([0,1], [0,1])
ax.set_title("a straight line (OO)")
ax.set_xlabel("x value")
ax.set_ylabel("y value") canvas.print_figure('demo.jpg')

上面的例子中,我们至少构建了四个对象: fig, canvas, ax, line。它们分别属于Figure类,FigureCanvas类,Axes类和Line2D类。(使用obj.__class__.__name__来查询对象所属的类)
在深入各个对象之前,我们先来做一个比喻。看下面一个图片:

可以看到,图中有一个房子,房子上有窗户和门,窗户上有条纹,门上有把手,此外图像外还有一只小乌龟。我们所提到的房子,窗户,门,条纹,把手,都可以称其为对象。不同的对象之间有依附关系,比如窗户和门属于房子,而把手属于门。乌龟和房子则是并行的两个对象。此外,整个图像外有一个方框,用来表明可绘图的范围,所有上面提到的元素都依附于该方框。
这就是用面向对象的方式来理解一个图像。事实上,对象是描述图像的最自然的方式,面向对象编程最成功的领域就是在计算机图形方面。
我们先来看什么是Figure和Axes对象。在matplotlib中,整个图像为一个Figure对象。在Figure对象中可以包含一个,或者多个Axes对象。每个Axes对象都是一个拥有自己坐标系统的绘图区域。其逻辑关系如下:

转过头来看直线图。整个图像是fig对象。我们的绘图中只有一个坐标系区域,也就是ax。此外还有以下对象。(括号中表示对象的基本类型)

Title为标题。Axis为坐标轴,Label为坐标轴标注。Tick为刻度线,Tick Label为刻度注释。各个对象之间有下面的对象隶属关系:

(yaxis同样有tick, label和tick label,没有画出)
尽管data是数据绘图的关键部分,也就是数据本身的图形化显示,但是必须和xaxis, yaxis, title一起,才能真正构成一个绘图区域axes。一个单纯的,无法读出刻度的线是没有意义的。xaxis, yaxis, title合起来构成了数据的辅助部分(data guide)。
上面元素又包含有多种图形元素。比如说,我们的data对象是一条线(Line2D)。title, tick label和label都是文本(Text),而tick是由短线(Line 2D)和tick label构成,xaxis由坐标轴的线和tick以及label构成,ax由xaxis, yaxis, title, data构成,ax自身又构成了fig的一部分。上面的每个对象,无论是Line2D, Text还是fig,它们都来自于一个叫做Artist的基类。
OO绘图的原程序还有一个canvas对象。它代表了真正进行绘图的后端(backend)。Artist只是在程序逻辑上的绘图,它必须连接后端绘图程序才能真正在屏幕上绘制出来(或者保存为文件)。我们可以将canvas理解为绘图的物理(或者说硬件)实现。
在OO绘图程序中,我们并没有真正看到title, tick, tick label, xaxis, yaxis对象,而是使用ax.set_*的方法间接设置了这些对象。但这些对象是真实存在的,你可以从上层对象中找到其“真身”。比如,fig.axes[0].xaxis就是我们上面途中的xaxis对象。我们可以通过fig -> axes[0] (也就是ax) -> xaxis的顺序找到它。因此,重复我们刚才已经说过的,一个fig就构成了一个完整的图像。对于每个Artist类的对象,都有findobj()方法,来显示该对象所包含的所有下层对象。
坐标
坐标是计算机绘图的基础。计算机屏幕是由一个个像素点构成的。想要在屏幕上显示图像,计算机必须告诉屏幕每个像素点上显示什么。所以,最贴近硬件的坐标体系是以像素为单位的坐标体系。我们可以通过具体说明像素位置来标明显示器上的某一点。这叫做显示坐标(display coordinate),以像素为单位。
然而,像素坐标不容易被纳入绘图逻辑。相同的程序,在不同的显示器上就要调整像素值,以保证图像不变形。所以一般情况下,还会有图像坐标和数据坐标。
图像坐标将一张图的左下角视为原点,将图像的x方向和y方向总长度都看做1。x方向的0.2就是指20%的图像在x方向的总长,y方向0.8的长度指80%的y方向总长。(0.5, 0.5)是图像的中点,(1, 1)指图像的右上角。比如下面的程序,我们在使用add_axes时,传递的参数中,前两个元素为axes的左下角在fig的图像坐标上的位置,后两个元素指axes在fig的图像坐标上x方向和y方向的长度。fig的图像坐标称为Figure坐标,储存在为fig.transFigure
(类似的,每个axes,比如ax1,有属于自己的图像坐标。它以ax1绘图区域总长作为1,称为Axes坐标。也就是ax1.transAxes。(0.5, 0.5)就表示在Axes的中心。Axes坐标和Figure坐标原理相似,只是所用的基准区域不同。)
from matplotlib.figure import Figure
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas fig = Figure()
canvas = FigureCanvas(fig) # first axes
ax1 = fig.add_axes([0.1, 0.1, 0.2, 0.2])
line, = ax1.plot([0,1], [0,1])
ax1.set_title("ax1") # second axes
ax2 = fig.add_axes([0.4, 0.3, 0.4, 0.5])
sca = ax2.scatter([1,3,5],[2,1,2])
ax2.set_title("ax2") canvas.print_figure('demo.jpg')
我们在绘图,比如使用plot的时候,绘制了两点间的连线。这两点分别为(0, 0)和(1, 1)。(plot中的第一个表为两个x坐标,第二个表为两个y坐标)。这时使用的坐标系为数据坐标系(ax1.transData)。我们可以通过绘出的坐标轴读出数据坐标的位置。

如果绘制的是具体数据,那么数据坐标符合我们的需求。如果绘制的是标题这样的附加信息,那么Axes坐标符合符合我们的需求。如果是整个图像的注解,那么Figure坐标更符合需求。每一个Artist对象都有一个transform属性,用于查询和改变所使用的坐标系统。如果为显示坐标,transform属性为None。
参考资料:
(1) http://www.cnblogs.com/vamei/archive/2013/01/30/2879700.html
(2) http://hyry.dip.jp/tech/book/page/scipy/matplotlib_fast_plot.html
(3) http://liam0205.me/2014/09/11/matplotlib-tutorial-zh-cn/
(4) http://reverland.org/python/2012/09/07/matplotlib-tutorial/
(5) http://www.yeolar.com/note/2011/04/28/matplotlib-tips/
理解matplotlib绘图的更多相关文章
- matplotlib 绘图
http://blog.csdn.net/jkhere/article/details/9324823 都打一遍 5 matplotlib-绘制精美的图表 matplotlib 是python最著名的 ...
- matplotlib绘图基本用法-转自(http://blog.csdn.net/mao19931004/article/details/51915016)
本文转载自http://blog.csdn.net/mao19931004/article/details/51915016 <!DOCTYPE html PUBLIC "-//W3C ...
- python实战学习之matplotlib绘图续
学习完matplotlib绘图可以设置的属性,还需要学习一下除了折线图以外其他类型的图如直方图,条形图,散点图等,matplotlib还支持更多的图,具体细节可以参考官方文档:https://matp ...
- matplotlib绘图的基本操作
转自:Laumians博客园 更简明易懂看Matplotlib Python 画图教程 (莫烦Python)_演讲•公开课_科技_bilibili_哔哩哔哩 https://www.bilibili. ...
- python中利用matplotlib绘图可视化知识归纳
python中利用matplotlib绘图可视化知识归纳: (1)matplotlib图标正常显示中文 import matplotlib.pyplot as plt plt.rcParams['fo ...
- python实战学习之matplotlib绘图
matplotlib 是最流行的Python底层绘图库,主要做数据可视化图表 可以将数据可视化,能够更直观的呈现数据 matplotlib绘图基本要点 首先实现一个简单的绘图 # 导入pyplot f ...
- 【原】在Matplotlib绘图中添加Latex风格公式
Matplotlib绘图的过程中,可以为各个轴的Label,图像的Title.Legend等元素添加Latex风格的公式. 只需要在Latex公式的文本前后各增加一个$符号,Matplotlib就可以 ...
- Matplotlib绘图双纵坐标轴设置及控制设置时间格式
双y轴坐标轴图 今天利用matplotlib绘图,想要完成一个双坐标格式的图. fig=plt.figure(figsize=(20,15)) ax1=fig.add_subplot(111) ax1 ...
- ssh调用matplotlib绘图报错RuntimeError: Invalid DISPLAY variable
1.问题:在本地用matplotlib绘图可以,但是在ssh远程绘图的时候会报错 RuntimeError: Invalid DISPLAY variable 2.原因:matplotlib的默认ba ...
随机推荐
- POJ 2007 Scrambled Polygon (简单极角排序)
题目链接 题意 : 对输入的点极角排序 思路 : 极角排序方法 #include <iostream> #include <cmath> #include <stdio. ...
- JAVA IO 类库详解
JAVA IO类库详解 一.InputStream类 1.表示字节输入流的所有类的超类,是一个抽象类. 2.类的方法 方法 参数 功能详述 InputStream 构造方法 available 如果用 ...
- Linux网络编程5——使用UDP协议实现群聊
引言 本文实现的功能类似于我之前所写的一篇博文(Linux之select系统调用_2),区别在于进程之间的通信方式有所不同.之前的文章中,我所使用的是管道,而本文我将会使用socket接口. 需求 客 ...
- js的in运算符与instanceof运算符
in运算符:希望他的左操作数是一个字符串或可以转换为字符串,希望他的右操作数是一个对象.如果右操作数的对象拥有一个名为左操作数值的属性名,那么表达式返回true. var point= {x:1,y: ...
- 连接池和 "Timeout expired"异常【转】
异常信息: MySql.Data.MySqlClient.MySqlException (0x80004005): error connecting: Timeout expired. The tim ...
- java理论基础学习二
JAVA开发工具 文本编辑器 UltraEdit EditPlus notepad++ 集成开发环境 IDE Integrated Development Enviroment JBuilder h ...
- http://blog.csdn.net/woshiyjk/article/details/7895888
http://blog.csdn.net/woshiyjk/article/details/7895888
- 二分图点染色 BestCoder 1st Anniversary($) 1004 Bipartite Graph
题目传送门 /* 二分图点染色:这题就是将点分成两个集合就可以了,点染色用dfs做, 剩下的点放到点少的集合里去 官方解答:首先二分图可以分成两类点X和Y, 完全二分图的边数就是|X|*|Y|.我们的 ...
- YARN集群维护部分问题汇总
云梯开发人员在云梯Yarn集群的搭建和维护过程中做了许多工作,本文选择这期间部分较为典型的问题,通过对这些问题的分析和解决方案,为大家分享分布式系统问题调查的经验. 调查的问题 1. 2013年初引入 ...
- RTMP/RTP/RTSP/RTCP的区别
RTCP RTMP/RTP/RTSP/RTCP的区别 http://blog.csdn.net/frankiewang008/article/details/7665547 流媒体协议介绍(rtp/r ...