一、相关知识
官网介绍
相关博客
fig, ax = plt.subplots(2,2),其中参数分别代表子图的行数和列数,一共有 2x2 个图像。函数返回一个figure图像和一个子图ax的array列表。
补充:gridspec命令可以对子图区域划分提供更灵活的配置。
中文显示方框问题
这是由于matplotlib文件夹内没有中文字体包导致的,实际上函数包本身是支持中文的,常见解决方案是拷贝字体文件到matplotlib中,不过我感觉太麻烦,找到了另外的方式,
from pylab import mpl mpl.rcParams[\'font.sans-serif\'] = [\'FangSong\'] # 指定默认字体 mpl.rcParams[\'axes.unicode_minus\'] = False # 解决保存图像是负号\'-\'显示为方块的问题
加上这三行代码指定一下字体就行了(实际上最后一行可以不加)
anaconda字体路径在:/anaconda2/lib/python2.7/site-packages/matplotlib/mpl-data/font/ttf
一、常用绘制流程
1.axes列表中包含各个子图句柄
# 3x3子图
fig, axes = plt.subplots(3, 3)
# 子图间距设定
fig.subplots_adjust(hspace=0.3, wspace=0.3)
# 在分别绘制各个子图
for i, ax in enumerate(axes.flat):
pass
2.每个子图句柄需要单独生成
# 画布 fig = plt.figure() # 添加子图 ax = fig.add_subplot(211) pass # 添加子图 ax2 = fig.add_subplot(212) pass
3.使用plt包命名空间代指多个子图句柄
【注】这种方法的句柄含在plt中,与上面的ax的方法属性并不相同,下面会详解
# 添加子图 plt.subplot(311) pass # 添加子图 plt.subplot(312) pass # 添加子图 plt.subplot(313) pass
二、绘图功能
【注】使用ax代指子图方法1、2的句柄,plt代指方法3中的命名空间。坐标生成:
# 一维坐标生成 x = np.linspace(0,10,100) # 二维网格生成 u = np.linspace(-1,1,100) x,y = np.meshgrid(u,u)
坐标轴标签:
xlabel = "True: {0}, Pred: {1}".format(cls_true[i], cls_pred[i])
xlabel = "y"
ax.set_xlabel(xlabel)
ax.set_ylabel(ylabel)
plt.xlabel(\'x\')
plt.ylabel(\'y\')
坐标轴刻度:
ax.set_xticks([]) ax.set_yticks([]) plt.xticks(range(len(x)), [\'a\', \'b\', \'c\', \'d\', \'e\', \'f\']) plt.yticks(range(1, 8, 2))
坐标网格:
# 横纵坐标单位长度统一 plt.axis(\'equal\') # 网格 plt.grid(True) # 网格 ax.grid(True)
图表标题:
plt.title(\'Second Derivative\')
对数坐标:
\'\'\'对数坐标\'\'\' plt.semilogx(x,y) # 对x取对数 plt.semilogy(x,y) # 对y取对数 plt.loglog(x,y) # 同时取对数
绘图:
# 色彩填充 ax.fill(x,y1,facecolor=\'g\',alpha=0.3) ax.fill_between(x,y,y1,facecolor=\'b\') # 等高线 ax.contourf(x,y,z) # 显示数组,因为是数组所以才会有vmin和vmax的关键字 ax.imshow() # 线性绘图 plt.plot(x,y1,c=\'b\',linestyle=\'\',marker=\'^\')
三、经典实例
饼状图
import matplotlib.pyplot as plt
plt.figure(figsize=(12,9))
labels = [\'part1\', \'part2\', \'part3\']
# 各个饼的比例
sizes = [30, 20, 50]
colors = [\'yellowgreen\', \'gold\', \'lightskyblue\']
# 各个模块离圆心的距离,参数为距离
explode = (0.05, 0.0, 0.0)
# 图 label的text 比例的text
patches, l_texts, p_texts = plt.pie(sizes, explode=explode, labels=labels, colors=colors, labeldistance=0.8,
autopct=\'%3.1f%%\', shadow=True, startangle=90, pctdistance=0.6)
# 设置x,y轴刻度一致,这样饼图才能是圆的
plt.axis(\'equal\')
plt.legend()
# 设置label的字体大小
for t in l_texts:
t.set_size(20)
# 设置比例数字的字体大小
for t in p_texts:
t.set_size(20)
plt.show()
柱状图
import numpy as np
from matplotlib import pyplot as plt
plt.figure(figsize=(9,6))
n = 12
X = np.arange(n)+1
# numpy.random.uniform(low=0.0, high=1.0, size=None), normal
Y1 = (1-X/float(n+1)) * np.random.uniform(0.5,1.0,n)
Y2 = (1-X/float(n+1)) * np.random.uniform(0.5,1.0,n)
# bar and barh
width = 0.35
plt.bar(X, Y1, width=width, facecolor=\'#9999ff\', edgecolor=\'white\')
plt.bar(X+width, Y2, width=width, facecolor=\'#ff9999\', edgecolor=\'white\')
plt.bar(X, -Y2, width=width, facecolor=\'#ff9999\', edgecolor=\'white\')
# 柱状图添加说明文字
for x,y in zip(X,Y1):
plt.text(x, y+0.05, \'%.2f\' % y, ha=\'center\', va= \'bottom\')
for x,y in zip(X,-Y2):
plt.text(x+0.4, y-0.15, \'%.2f\' % y, ha=\'center\', va= \'bottom\')
#plt.ylim(-1.25,+1.25)
plt.show()
import numpy as np from matplotlib import pyplot as plt plt.figure(figsize=(9,6)) n = 12 X = np.arange(n)+1 # numpy.random.uniform(low=0.0, high=1.0, size=None), normal Y1 = (1-X/float(n+1)) * np.random.uniform(0.5,1.0,n) Y2 = (1-X/float(n+1)) * np.random.uniform(0.5,1.0,n) # bar and barh width = 0.35 # 方法barh和参数height可以实现横向的柱状图 plt.barh(X, Y1, height=width, facecolor=\'#9999ff\', edgecolor=\'white\') plt.show()
概率分布图
from matplotlib import pyplot as plt import numpy as np mu = 0 sigma = 1 x = mu + sigma*np.random.randn(10000) fig,(ax0,ax1)=plt.subplots(ncols=2, figsize=(9,6)) ax0.hist(x, 20, normed=1, histtype=\'bar\', facecolor=\'g\', rwidth=0.8, alpha=0.75) ax0.set_title(\'pdf\') # 累积概率密度分布 ax1.hist(x, 20, normed=1, histtype=\'bar\', rwidth=0.8, cumulative=True) ax1.set_title(\'cdf\') plt.show()
散点图
atan2(a,b)是4象限反正切,它的取值不仅取决于正切值a/b,还取决于点 (b, a) 落入哪个象限: 当点(b, a) 落入第一象限时,atan2(a,b)的范围是 0 ~ pi/2; 当点(b, a) 落入第二象限时,atan2(a,b)的范围是 pi/2 ~ pi; 当点(b, a) 落入第三象限时,atan2(a,b)的范围是 -pi~-pi/2; 当点(b, a) 落入第四象限时,atan2(a,b)的范围是 -pi/2~0
而 atan(a/b) 仅仅根据正切值为a/b求出对应的角度 (可以看作仅仅是2象限反正切): 当 a/b > 0 时,atan(a/b)取值范围是 0 ~ pi/2; 当 a/b < 0 时,atan(a/b)取值范围是 -pi/2~0
故 atan2(a,b) = atan(a/b) 仅仅发生在 点 (b, a) 落入第一象限 (b>0, a>0)或 第四象限(b>0, a0 , 故 atan(a/b) 取值范围是 0 ~ pi/2,2atan(a/b) 的取值范围是 0 ~ pi,而此时atan2(a,b)的范围是 -pi~-pi/2,很显然,atan2(a,b) = 2atan(a/b)
举个最简单的例子,a = 1, b = -1,则 atan(a/b) = atan(-1) = -pi/4, 而 atan2(a,b) = 3*pi/4
from matplotlib import pyplot as plt import numpy as np plt.figure(figsize=(9,6)) n = 1024 # 均匀分布 高斯分布 # rand 和 randn X = np.random.rand(1,n) Y = np.random.rand(1,n) # 设定颜色 T = np.arctan2(Y,X) plt.scatter(X,Y, s=75, c=T, alpha=.4, marker=\'o\') #plt.xlim(-1.5,1.5), plt.xticks([]) #plt.ylim(-1.5,1.5), plt.yticks([]) plt.show()
不规则组合图
# 定义子图区域
left, width = 0.1, 0.65
bottom, height = 0.1, 0.65
bottom_h = left_h = left + width + 0.02
rect_scatter = [left, bottom, width, height]
rect_histx = [left, bottom_h, width, 0.2]
rect_histy = [left_h, bottom, 0.2, height]
plt.figure(1, figsize=(6, 6))# 需要传入[左边起始位置,下边起始位置,宽,高]
# 根据子图区域来生成子图
axScatter = plt.axes(rect_scatter)
axHistx = plt.axes(rect_histx)
axHisty = plt.axes(rect_histy)
# ref : http://matplotlib.org/examples/pylab_examples/scatter_hist.html import numpy as np import matplotlib.pyplot as plt # the random data x = np.random.randn(1000) y = np.random.randn(1000) # 定义子图区域 left, width = 0.1, 0.65 bottom, height = 0.1, 0.65 bottom_h = left_h = left + width + 0.02 rect_scatter = [left, bottom, width, height] rect_histx = [left, bottom_h, width, 0.2] rect_histy = [left_h, bottom, 0.2, height] plt.figure(1, figsize=(6, 6)) # 根据子图区域来生成子图 axScatter = plt.axes(rect_scatter) axHistx = plt.axes(rect_histx) axHisty = plt.axes(rect_histy) # no labels #axHistx.xaxis.set_ticks([]) #axHisty.yaxis.set_ticks([]) # now determine nice limits by hand: N_bins=20 xymax = np.max([np.max(np.fabs(x)), np.max(np.fabs(y))]) binwidth = xymax/N_bins lim = (int(xymax/binwidth) + 1) * binwidth nlim = -lim # 画散点图,概率分布图 axScatter.scatter(x, y) axScatter.set_xlim((nlim, lim)) axScatter.set_ylim((nlim, lim)) bins = np.arange(nlim, lim + binwidth, binwidth) axHistx.hist(x, bins=bins) axHisty.hist(y, bins=bins, orientation=\'horizontal\') # 共享刻度 axHistx.set_xlim(axScatter.get_xlim()) axHisty.set_ylim(axScatter.get_ylim()) plt.show()
三维数据图
使用散点图的点大小、颜色、透明度表示高维数据:
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(9,6),facecolor=\'white\')
# Number of ring
n = 50
size_min = 50
size_max = 50*50
# Ring position
P = np.random.rand(n,2)
# Ring colors R,G,B,A
C = np.ones((n,4)) * (0.5,0.5,0,1)
# Alpha color channel goes from 0 (transparent) to 1 (opaque),很厉害的实现
C[:,3] = np.linspace(0,1,n)
# Ring sizes
S = np.linspace(size_min, size_max, n)
# Scatter plot
plt.scatter(P[:,0], P[:,1], s=S, lw = 0.5,
edgecolors = C, facecolors=C)
plt.xlim(0,1), plt.xticks([])
plt.ylim(0,1), plt.yticks([])
plt.show()
美化
# 美化matplotlib绘出的图,导入后自动美化 import seaborn as sns # matplotlib自带美化风格 # 打印可选风格 print(plt.style.available #ggplot, bmh, dark_background, fivethirtyeight, grayscale) # 激活风格 plt.style.use(\'bmh\')
一维颜色填充 & 三维绘图 & 三维等高线图
『Python』Numpy学习指南第九章_使用Matplotlib绘图
from mpl_toolkits.mplot3d import Axes3D
ax = fig.add_subplot(111,projection=\'3d\')
ax.plot() 绘制3维线
ax.plot_surface绘制三维网格(面)
from mpl_toolkits.mplot3d import Axes3D #<-----导入3D包 import numpy as np import matplotlib.pyplot as plt fig = plt.figure(figsize=(9,6)) ax = fig.add_subplot(111,projection=\'3d\') #<-----设置3D模式子图
# 新思路,之前都是生成x和y绘制z=f(x,y)的函数,这次绘制x=f1(z),y=f2(z) z = np.linspace(0, 6, 1000) r = 1 x = r * np.sin(np.pi*2*z) y = r * np.cos(np.pi*2*z) ax.plot(x, y, z, label=u\'螺旋线\', c=\'r\') ax.legend() # dpi每英寸长度的点数 plt.savefig(\'3d_fig.png\',dpi=200) plt.show()
# ax.plot 绘制的是3维线,ax.plot_surface绘制的是三维网格(也就是面)
from mpl_toolkits.mplot3d import axes3d import matplotlib.pyplot as plt from matplotlib import cm fig = plt.figure() ax = fig.add_subplot(111,projection=\'3d\') X, Y, Z = axes3d.get_test_data(0.05) print(X,Y,Z) # ax.plot 绘制的是3维线,ax.plot_surface绘制的是三维网格(也就是面) ax.plot_surface(X, Y, Z, rstride=5, cstride=5, alpha=0.3) # 三维图投影制作,zdir选择投影方向坐标轴 cset = ax.contour(X, Y, Z, 10, zdir=\'z\', offset=-100, cmap=cm.coolwarm) cset = ax.contour(X, Y, Z, zdir=\'x\', offset=-40, cmap=cm.coolwarm) cset = ax.contour(X, Y, Z, zdir=\'y\', offset=40, cmap=cm.coolwarm) ax.set_xlabel(\'X\') ax.set_xlim(-40, 40) ax.set_ylabel(\'Y\') ax.set_ylim(-40, 40) ax.set_zlabel(\'Z\') ax.set_zlim(-100, 100) plt.show()
# 为等高线图添加标注
cs = ax2.contour(X,Y,Z) ax2.clabel(cs, inline=1, fontsize=5)
配置Colorbar
# -*- coding: utf-8 -*-
#**********************************************************
import os
import numpy as np
import wlab #pip install wlab
import matplotlib
import matplotlib.cm as cm
import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator
from scipy.interpolate import griddata
matplotlib.rcParams[\'xtick.direction\'] = \'out\'
matplotlib.rcParams[\'ytick.direction\'] = \'out\'
#**********************************************************
FreqPLUS=[\'F06925\',\'F10650\',\'F23800\',\'F18700\',\'F36500\',\'F89000\']
#
FindPath=\'/d3/MWRT/R20130805/\'
#**********************************************************
fig = plt.figure(figsize=(8,6), dpi=72, facecolor="white")
axes = plt.subplot(111)
axes.cla()#清空坐标轴内的所有内容
#指定图形的字体
font = {\'family\' : \'serif\',
\'color\' : \'darkred\',
\'weight\' : \'normal\',
\'size\' : 16,
}
#**********************************************************
# 查找目录总文件名中保护F06925,EMS和txt字符的文件
for fp in FreqPLUS:
FlagStr=[fp,\'EMS\',\'txt\']
FileList=wlab.GetFileList(FindPath,FlagStr)
#
LST=[]#地表温度
EMS=[]#地表发射率
TBH=[]#水平极化亮温
TBV=[]#垂直极化亮温
#
findex=0
for fn in FileList:
findex=findex+1
if (os.path.isfile(fn)):
print(str(findex)+\'-->\'+fn)
#fn=\'/d3/MWRT/R20130805/F06925_EMS60.txt\'
data=wlab.dlmread(fn)
EMS=EMS+list(data[:,1])#地表发射率
LST=LST+list(data[:,2])#温度
TBH=TBH+list(data[:,8])#水平亮温
TBV=TBV+list(data[:,9])#垂直亮温
#-----------------------------------------------------------
#生成格点数据,利用griddata插值
grid_x, grid_y = np.mgrid[275:315:1, 0.60:0.95:0.01]
grid_z = griddata((LST,EMS), TBH, (grid_x, grid_y), method=\'cubic\')
#将横纵坐标都映射到(0,1)的范围内
extent=(0,1,0,1)
#指定colormap
cmap = matplotlib.cm.jet
#设定每个图的colormap和colorbar所表示范围是一样的,即归一化
norm = matplotlib.colors.Normalize(vmin=160, vmax=300)
#显示图形,此处没有使用contourf #>>>ctf=plt.contourf(grid_x,grid_y,grid_z)
gci=plt.imshow(grid_z.T, extent=extent, origin=\'lower\',cmap=cmap, norm=norm)
#配置一下坐标刻度等
ax=plt.gca()
ax.set_xticks(np.linspace(0,1,9))
ax.set_xticklabels( (\'275\', \'280\', \'285\', \'290\', \'295\', \'300\', \'305\', \'310\', \'315\'))
ax.set_yticks(np.linspace(0,1,8))
ax.set_yticklabels( (\'0.60\', \'0.65\', \'0.70\', \'0.75\', \'0.80\',\'0.85\',\'0.90\',\'0.95\'))
#显示colorbar
cbar = plt.colorbar(gci)
cbar.set_label(\'$T_B(K)$\',fontdict=font)
cbar.set_ticks(np.linspace(160,300,8))
cbar.set_ticklabels( (\'160\', \'180\', \'200\', \'220\', \'240\', \'260\', \'280\', \'300\'))
#设置label
ax.set_ylabel(\'Land Surface Emissivity\',fontdict=font)
ax.set_xlabel(\'Land Surface Temperature(K)\',fontdict=font) #陆地地表温度LST
#设置title
titleStr=\'$T_B$ for Freq = \'+str(float(fp[1:-1])*0.01)+\'GHz\'
plt.title(titleStr)
figname=fp+\'.png\'
plt.savefig(figname)
plt.clf()#清除图形
#plt.show()
print(\'ALL -> Finished OK\')
上面的例子中,每个保存的图,都是用同样的colormap,并且每个图的颜色映射值都是一样的,也就是说第一个图中如果200表示蓝色,那么其他图中的200也表示蓝色。
示例的图形如下: