Python的matplotlib(2)

来源:互联网 发布:淘宝最诚信的邮票商家 编辑:程序博客网 时间:2024/05/22 00:39

1、基础理解

1.1 函数式绘图

Python中的函数式编程是通过封装对象实现的。matplotlib中的函数式调用其实也是如此。matplotlib本质上还是构建对象来构建图像。函数式编程将构建对象的过程封装在函数中,从而让我们觉得很方便。
在matplotlib.pyplot中,你还可以找到下面的绘图函数

import numpy as npimport matplotlib.pyplot as pltimport matplotlib.patches# 1D datax = [1,2,3,4,5]y = [2.3,3.4,1.2,6.6,7.0]plt.figure(figsize=(12,6))plt.subplot(231)plt.plot(x,y)  plt.title("plot")plt.subplot(232)plt.scatter(x, y) # 散点图plt.title("scatter")plt.subplot(233)plt.pie(y)  # 饼图plt.title("pie") plt.subplot(234)plt.bar(x, y) # 直方图plt.title("bar")# 2D datadelta = 0.025x = y = np.arange(-3.0, 3.0, delta)X, Y = np.meshgrid(x, y)  # 网格Z    = Y**2 + X**2plt.subplot(235)plt.contour(X,Y,Z) # 轮廓图plt.colorbar() # 旁边的彩条plt.title("contour")# read imageimport matplotlib.image as mpimgimg=mpimg.imread('mar.jpg') # 把图片放在和.py文件同级的目录下plt.subplot(236)plt.imshow(img)plt.title("imshow")plt.savefig("matplot_sample.jpg")

这里写图片描述

1.2 面向对象编程

将上面的直线绘图更改为面向对象式(OO, object-oriented)的,为此,引入两个类: Figure和FigureCanvas。(函数式编程也调用了这些类,只是调用的过程被函数调用所遮掩。)

from matplotlib.figure import Figurefrom matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvasfig    = 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__来查询对象所属的类)

在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()方法,来显示该对象所包含的所有下层对象。

1.3 坐标

图像坐标将一张图的左下角视为原点,将图像的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 Figurefrom matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvasfig    = plt.Figure()canvas = FigureCanvas(fig)# first axesax1    = fig.add_axes([0.1, 0.1, 0.2, 0.2])line,  = ax1.plot([0,1], [0,1])ax1.set_title("ax1")# second axesax2    = 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')

这里写图片描述

这两点分别为(0, 0)和(1, 1)。(plot中的第一个表为两个x坐标,第二个表为两个y坐标)。这时使用的坐标系为数据坐标系(ax1.transData)。我们可以通过绘出的坐标轴读出数据坐标的位置。

如果绘制的是标题这样的附加信息,那么Axes坐标符合符合我们的需求。如果是整个图像的注解,那么Figure坐标更符合需求。每一个Artist对象都有一个transform属性,用于查询和改变所使用的坐标系统。如果为显示坐标,transform属性为None。

深入基础

from matplotlib.figure import Figurefrom matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvasfig    = Figure()canvas = FigureCanvas(fig)ax     = fig.add_axes([0.1, 0.1, 0.8, 0.8])from matplotlib.path import Pathimport matplotlib.patches as patchesverts = [    (0., 0.),     (3., 0.),    (4., 2.8),    (5.,0.),    (8.,0.),    (5.5, -1.7),    (7.2, -4.7),    (4., -2.7),    (0.8, -4.7),    (2.5, -1.7),    (0.,0.),    ]codes = [Path.MOVETO,         Path.LINETO,         Path.LINETO,         Path.LINETO,         Path.LINETO,         Path.LINETO,         Path.LINETO,         Path.LINETO,         Path.LINETO,         Path.LINETO,         Path.CLOSEPOLY,         ]path = Path(verts, codes)patch = patches.PathPatch(path, facecolor='red')ax.add_patch(patch)ax.set_xlim(-1.8,9)ax.set_ylim(-5.7,3.8)canvas.print_figure('demo.jpg')

在上面的程序中。我们首先确定顶点,然后构建了一个path对象,在codes中,我们先使用MOVETO将画笔移动到起点,然后依次用直线连接(LINETO)(我们也可以用曲线来连线,比如CURVE4,但这里没有用到)。 在path建立了封闭的图形后,我们在path的基础上构建了patch对象,是一个图形块。最后,我们将这个patch对象添加到预先准备好的ax上,就完成了整个绘图。

这里写图片描述

2 应用

2.1 为项目设置matplotlib参数

如果不想每次使用matplotlib时都在代码部分进行配置,可以修改matplotlib的文件参数。可以用matplot.get_config()命令来找到当前用户的配置文件目录。
配置文件包括以下配置项:

axex: 设置坐标轴边界和表面的颜色、坐标刻度值大小和网格的显示
backend: 设置目标暑促TkAgg和GTKAgg
figure: 控制dpi、边界颜色、图形大小、和子区( subplot)设置
font: 字体集(font family)、字体大小和样式设置
grid: 设置网格颜色和线性
legend: 设置图例和其中的文本的显示
line: 设置线条(颜色、线型、宽度等)和标记
patch: 是填充2D空间的图形对象,如多边形和圆。控制线宽、颜色和抗锯齿设置等。
savefig: 可以对保存的图形进行单独设置。例如,设置渲染的文件的背景为白色。
verbose: 设置matplotlib在执行期间信息输出,如silent、helpful、debug和debug-annoying。
xticks和yticks: 为x,y轴的主刻度和次刻度设置颜色、大小、方向,以及标签大小。

2.2 确定坐标范围

  • plt.axis([xmin, xmax, ymin, ymax]): axis()命令给定了坐标范围。

  • xlim(xmin, xmax)和ylim(ymin, ymax)来调整x,y坐标范围

import numpy as np  import matplotlib.pyplot as plt  from pylab import *  x = np.arange(-5.0, 5.0, 0.02)  y1 = np.sin(x)  plt.figure(1)  plt.subplot(211)  plt.plot(x, y1)  plt.subplot(212)  #设置x轴范围  xlim(-2.5, 2.5)  #设置y轴范围  ylim(-1, 1)  plt.plot(x, y1)  

这里写图片描述

上图可以看出第二张是第一张的细节图

2.3 叠加图

import numpy as np  import matplotlib.pyplot as plt  t = np.arange(0., 5., 0.2)  plt.plot(t, t, 'r--', t, t**2, 'bs', t, t**3, 'g^')  plt.show()  

这里写图片描述

2.4 plt.figure()

你可以多次使用figure命令来产生多个图,其中,图片号按顺序增加。这里,要注意一个概念当前图和当前坐标。所有绘图操作仅对当前图和当前坐标有效。

import numpy as npimport matplotlib.pyplot as pltimport matplotlib.patchesplt.figure(1) # 第一张图  plt.subplot(211) # 第一张图中的第一张子图  plt.plot([1,2,3])  plt.subplot(212) # 第一张图中的第二张子图  plt.plot([4,5,6])  plt.figure(2) # 第二张图  plt.plot([4,5,6]) # 默认创建子图subplot(111)plt.figure(1) # 切换到figure 1 ; 子图subplot(212)仍旧是当前图  plt.subplot(211) # 令子图subplot(211)成为figure1的当前图  plt.title('Easy as 1,2,3') # 添加subplot 211 的标题 

这里写图片描述
这里写图片描述

2.5 plt.text()添加文字说明

text()可以在图中的任意位置添加文字,并支持LaTex语法
xlable(), ylable()用于添加x轴和y轴标签
title()用于添加图的题目

import numpy as npimport matplotlib.pyplot as plt#import matplotlib.patchesmu, sigma = 100, 15  x = mu + sigma * np.random.randn(10000)  # 数据的直方图  n, bins, patches = plt.hist(x, 50, normed=1, facecolor='g', alpha=0.75)  plt.xlabel('Smarts')  plt.ylabel('Probability')  #添加标题  plt.title('Histogram of IQ')  #添加文字  plt.text(60, 0.025, r'$u=100,\ \sigma=15$')  # 前两个参数是文字起始位置plt.axis([40, 160, 0, 0.03])  # 坐标轴的范围plt.grid(True)  # 添加网格plt.show()   

这里写图片描述

2.6 plt.annotate()文本注释

在数据可视化的过程中,图片中的文字经常被用来注释图中的一些特征。使用annotate()方法可以很方便地添加此类注释。在使用annotate时,要考虑两个点的坐标:被注释的地方xy(x, y)和插入文本的地方xytext(x, y)

import numpy as npimport matplotlib.pyplot as plt#import matplotlib.patchesax = plt.subplot(111)  t = np.arange(0.0, 5.0, 0.01)  s = np.cos(2*np.pi*t)  # s=cos(2*pi*t)line, = plt.plot(t, s, lw=2)   # linewidth=2# local max是文本内容,xy是要注释的点的坐标,xytext是文本的坐标,shrink是其收缩的长度plt.annotate('local max', xy=(2, 1), xytext=(3, 1.5), \             arrowprops=dict(facecolor='black', shrink=0.05))plt.ylim(-2,2)  plt.show()  

这里写图片描述

2.7 plt.xticks()和plt.yticks()设置轴记号

人为设置坐标轴的刻度显示的值

import numpy as npimport matplotlib.pyplot as plt#import matplotlib.patchesfrom pylab import *  # 创建一个8 * 6 点(point)的图,并设置分辨率为80  figure(figsize=(8,6), dpi=80)  subplot(1,1,1)  X = np.linspace(-np.pi, np.pi, 256,endpoint=True)  C,S = np.cos(X), np.sin(X)  # 绘制余弦曲线,使用蓝色的、连续的、宽度为1(像素)的线条  plot(X, C, color="blue", linewidth=1.0, linestyle="-")  # 绘制正弦曲线,使用绿色的、连续的、宽度为4(像素)的线条  plot(X, S, color="r", lw=4.0, linestyle="-")  plt.axis([-4,4,-1.2,1.2])  # 设置轴记号  xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi],\          [r'$-\pi$', r'$-\pi/2$', r'$0$', r'$+\pi/2$', r'$+\pi$'])  yticks([-1, 0, +1],[r'$-1$', r'$0$', r'$+1$'])  show()  

这里写图片描述

2.8 移动spines

Spines 是连接轴刻度标记的线,而且标明了数据区域的边界。 他们可以被放置在任意位置。直到现在,他们仍是轴的边界。我们将要改变现状,因为我们想要spines 置于中间。因为有四个spine(上下左右),我们将要通过设置颜色(无)丢弃上面和右侧的部分。 进而我们移动下面和左边的线到坐标0(数据空间)。

import numpy as npimport matplotlib.pyplot as plt#import matplotlib.patchesfrom pylab import *  # 创建一个8 * 6 点(point)的图,并设置分辨率为80  figure(figsize=(8,6), dpi=80)  subplot(1,1,1)  X = np.linspace(-np.pi, np.pi, 256,endpoint=True)  C,S = np.cos(X), np.sin(X)  # 绘制余弦曲线,使用蓝色的、连续的、宽度为1(像素)的线条  plot(X, C, color="blue", linewidth=1.0, linestyle="-")  # 绘制正弦曲线,使用绿色的、连续的、宽度为4(像素)的线条  plot(X, S, color="r", lw=4.0, linestyle="-")  plt.axis([-4,4,-1.2,1.2])  # 设置轴记号  xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi],\          [r'$-\pi$', r'$-\pi/2$', r'$0$', r'$+\pi/2$', r'$+\pi$'])  yticks([-1, 0, +1],[r'$-1$', r'$0$', r'$+1$'])  ax = gca()  ax.spines['right'].set_color('none')   # 使右边的轴线消隐ax.spines['top'].set_color('none')    # 使上边的轴线消隐ax.xaxis.set_ticks_position('bottom')  # 设置x轴的tick的显示位置ax.spines['bottom'].set_position(('data',0)) ax.yaxis.set_ticks_position('left')   # 设置y轴的tick的显示位置ax.spines['left'].set_position(('data',0)) # 消隐左边的spine ,数据移动到坐标0plot(X, C, color="blue", linewidth=2.5, linestyle="-", label="cosine")  plot(X, S, color="red", linewidth=2.5, linestyle="-", label="sine")  legend(loc='upper left') t = 2*np.pi/3  # 两点分别是(t,0)和(t,np.cos(t))plot([t,t],[0,np.cos(t)], color ='blue', linewidth=2.5, linestyle="--") # scatter的第一个参数是x,第二个是y,在此得到的一个点(t,np.cos(t))scatter([t,],[np.cos(t),], 50, color ='blue') # xy()是注释点的坐标,xytext()是文本的坐标annotate(r'$\sin(\frac{2\pi}{3})=\frac{\sqrt{3}}{2}$',\    xy=(t, np.sin(t)),  xytext=(+10, +30), xycoords='data',\    textcoords='offset points',fontsize=16,arrowprops=dict(arrowstyle="->", \    connectionstyle="arc3,rad=.2"))  plot([t,t],[0,np.sin(t)], color ='red', linewidth=2.5, linestyle="--")  scatter([t,],[np.sin(t),], 50, color ='red') #  annotate(r'$\cos(\frac{2\pi}{3})=-\frac{1}{2}$',              xy=(t, np.cos(t)), xycoords='data',              xytext=(-90, -50), textcoords='offset points', fontsize=16,              arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=.2"))  show()

这里写图片描述

2.9 matplotlib.pyplot

使用plt.style.use(‘ggplot’)命令,可以作出ggplot风格的图片。

import numpy as npimport matplotlib.pyplot as plt#import matplotlib.patchesimport pandas as pd  plt.style.use('ggplot')  from sklearn import datasets,linear_model # Load data  boston = datasets.load_boston()  yb = boston.target.reshape(-1, 1)  Xb = boston['data'][:,5].reshape(-1, 1)  # Plot data  plt.scatter(Xb,yb)  plt.ylabel('value of house /1000 ($)')  plt.xlabel('number of rooms')  # Create linear regression object  regr = linear_model.LinearRegression()  # Train the model using the training sets  regr.fit( Xb, yb)  # Plot outputs  plt.scatter(Xb, yb, color='black')  plt.plot(Xb, regr.predict(Xb), color='blue',linewidth=3)  plt.show()  

这里写图片描述

2.10 plt.axes()

import numpy as npimport matplotlib.pyplot as plt#import matplotlib.patchesimport pandas as pd  plt.style.use('ggplot')  from sklearn import datasets,linear_model # create some data to use for the plotdt = 0.001  t = np.arange(0.0, 10.0, dt)  # 构建0到10的列表,间隔0.001r = np.exp(-t[:1000]/0.05)  # 脉冲响应 x = np.random.randn(len(t))  # 产生随机数s = np.convolve(x, r)[:len(x)]*dt # 卷积x,r 有色噪声  # the main axes is subplot(111) by default  plt.plot(t, s)  plt.axis([0, 1, 1.1*np.amin(s), 2*np.amax(s)])  plt.xlabel('time (s)')  plt.ylabel('current (nA)')  plt.title('Gaussian colored noise')  # 这是主轴上的一个插入轴 a = plt.axes([.65, .6, .2, .2], axisbg='y')  n, bins, patches = plt.hist(s, 400, normed=1)  plt.title('Probability')  plt.xticks([])  plt.yticks([]) #这是主轴上的另一个插入轴  a = plt.axes([0.2, 0.6, .2, .2], axisbg='y')  plt.plot(t[:len(r)], r)  plt.title('Impulse response')  plt.xlim(0, 0.2)  plt.xticks([])  plt.yticks([])  plt.show()  

这里写图片描述

其他的还有待学习。。。。

参考:

https://segmentfault.com/a/1190000005104723

http://www.cnblogs.com/vamei/archive/2013/01/30/2879700.html#commentform

原创粉丝点击