本文转载于 SegmentFault 社区

作者:mhxin


引言

首先来看几个简单的图表, 下面 4 段不同的 matplotlib 绘图代码最终的结果是一样的,绘制的图形如下图所示。

  
a = np.linspace(-5, 5, 100)b = np.sin(a)c = np.cos(a)

# -------------------------------------- ## ---------------First way-------------- #fig, ax = plt.subplots()ax.set_title('Sin-Cos')ax.set_xlabel('X')ax.set_ylabel('Y')ax.plot(a, b, c='r')ax.plot(a, c, c='g')ax.legend(['a', 'b'])fig.show()

# -------------------------------------- ## ---------------Second way-------------- #fig = plt.figure()ax = fig.add_subplot(111)ax.set_title('Sin-Cos')ax.set_xlabel('X')ax.set_ylabel('Y')ax.plot(a, b, c='r')ax.plot(a, c, c='g')ax.legend(['a', 'b'])fig.show()

# -------------------------------------- ## ---------------Third way-------------- #plt.figure()plt.title('Sin-Cos')plt.xlabel('X')plt.ylabel('Y')plt.plot(a, b, c='r')plt.plot(a, c, c='g')plt.legend(['a', 'b'])plt.show()

# -------------------------------------- ## ---------------Fourth way------------- #plt.subplot(111)plt.title('Sin-Cos')plt.xlabel('X')plt.ylabel('Y')plt.plot(a, b, c='r')plt.plot(a, c, c='g')plt.legend(['a', 'b'])plt.show()

在以上的 4 种实现方式中,可能大多数都会使用后面两种,即直接使用 plt.plot() 进行绘制,我刚开始也一样,它看起来简单,用起来也很方便。但当你逐渐习惯使用默认的方式来进行绘图时,慢慢会出现各种的问题,尤其是当你需要对图表使用很多自定义的设置的时候。默认接口隐藏了绘图过程中的很多细节,因为不了解其内部细节,所以在绘图过程中,对一些图表的设置方法全靠记忆。


Matplotlib 中的部件

好了,说了这么多,我们先来了解 matplotlib 绘图过程中几个主要的名称,如下图所示:

  • Figure 可以理解为画板,使用 fig = plt.figure() 会创建一个画板。
  • Axes可以理解为画板上的各种图形,一个图形就是一个 axes,利用 axes 可以对图形的各个部分进行设置。比如使用 fig.add_subplot() 会在 fig 上创建一个 axes。
  • Axis 表示一个 Axes 的坐标轴,比如 x 轴,y 轴以及 z 轴等。

接着,介绍图形(Axes)中的主要部件,了解了每个部件在图中的位置以及对应的功能之后才能按照自己的方式来对图表进行设置。以上图中的所有部件,都可以通过 axes 来实现精确的控制,比如需要设置 x 轴主刻度标签, 即可使用 axes.xaxis.set_ticklabels(['', '']),这种面向对象的控制方式,很容易理解和实现。


实战

基于上面的介绍,我们来绘制一些图形。

时间序列图

  直接上代码:

# 导入FontProperties类,该类用于定义字体,包括字体,大小等from matplotlib.font_manager import FontProperties

# 定义标签字体,字体为Time New Roman# 也可以通过指定fname(字体文件的路径)来定义字体label_font = FontProperties(family='Times New Roman', size=18, weight='bold', style='normal')

# 定义标题字体title_font = FontProperties(family='Times New Roman', size=20, weight='bold', style='normal')

# 定义坐标轴刻度字体ticks_font = FontProperties(family='Times New Roman', size=12, weight='bold', style='normal')

# 定义legend字体legend_font = FontProperties(family='Times New Roman', size=18, weight='bold', style='normal')

year = np.arange(1985, 2017, 1)ndvi = np.random.rand(len(year))

# 创建fig和axesfig, ax = plt.subplots(figsize=(10, 5))

# 取消x方向的格网# axis.xaxis.grid(False)# 取消y方向的格网# axis.yaxis.grid(False)

# 取消所有格网ax.grid(False)

# 定义标题,字体和颜色# axis.yaxis.label.set_fontproperties(font)# axis.xaxis.label.set_fontproperties(font)

ax.set_xlabel('Year', fontproperties=label_font, color='black')ax.set_ylabel('NDVI', fontproperties=label_font, color='black')

# 定义坐标轴显示范围ax.set_xlim(1985, 2017)ax.set_ylim(0, 1)

# 取消图表的上边界和右边界ax.spines['top'].set_visible(False)ax.spines['right'].set_visible(False)# 将图表的左边界和下边界的颜色设为黑色(默认为黑色)# 颜色可以参考:# https://matplotlib.org/3.1.3/gallery/color/color_demo.html#sphx-glr-gallery-color-color-demo-pyax.spines['left'].set_color('black')ax.spines['bottom'].set_color('black')

# 将图表的主刻度字体改为指定字体,并设定刻度不旋转,遍历所有主刻度for tick in ax.xaxis.get_majorticklabels():    tick.set_fontproperties(ticks_font)    tick.set_rotation(0)

for tick in ax.yaxis.get_majorticklabels():    tick.set_fontproperties(ticks_font)    tick.set_rotation(0)

# 设置图表的主刻度线的位置,x轴在下边,y轴在左边ax.yaxis.set_ticks_position('left')ax.xaxis.set_ticks_position('bottom')

# 设置显示的x主刻度ax.set_xticks(np.arange(1985, 2017, 3))

# 绘制时间序列ax.plot(year, ndvi)

# 设置第一条line(这里只有一条)的属性ax.lines[0].set_linewidth(2)ax.lines[0].set_linestyle('-')ax.lines[0].set_color('black')ax.lines[0].set_marker('*')ax.lines[0].set_markeredgecolor('red')

# 设置图例ax.legend(['TS1', ], prop=legend_font, facecolor='white')

#设置标题ax.set_title('Time Series', fontproperties=title_font, color='black')

plt.show()

绘制结果如下所示:绘制图表的代码虽然比较长,但结构比较清楚,结合前面的部件介绍,了解每一步的含义,相信很容易就能看懂。

带直方图的散点图

  代码如下:

# 定义坐标轴刻度字体ticks_font = FontProperties(family='Times New Roman', size=14, weight='normal', style='normal')

# 定义画板大小fig_width = 5

# space = fig_width / 100

left, bottom, width, height = fig_width / 10, fig_width / 10, fig_width / 2, fig_width / 2scatter_region = [left, bottom, width, height]topbar_region = [left, bottom +  height + space, width, height/2]rightbar_region = [left + width + space, bottom, width/2, height]

# 定义画板plt.figure(figsize=(fig_width, fig_width))

# 定义Axes用于绘制散点图# plt.axes([left, bottom, width, height])ax_scatter = plt.axes(scatter_region)

# 定义Axes用于绘制x的直方图ax_topbar = plt.axes(topbar_region)

# 定义Axes用于绘制y的直方图ax_rightbar = plt.axes(rightbar_region)

# ax_rightbar.invert_xaxis()# ax_topbar.xaxis.set_ticks([])# ax_rightbar.xaxis.set_ticks_position('bottom')# ax_rightbar.yaxis.set_ticks([])

# 设置坐标轴属性, 这里使用set_tick_params(),可以同时设置坐标轴的多个属性,详情可以参考:# https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.axes.Axes.tick_params.html#matplotlib.axes.Axes.tick_paramsax_rightbar.yaxis.set_tick_params(bottom=False, labelbottom=False)ax_rightbar.xaxis.set_tick_params(direction='out', color='black', left=True, labelleft=True)ax_topbar.yaxis.set_tick_params(direction='out', color='black', left=True, labelleft=True)ax_topbar.xaxis.set_tick_params(bottom=False, labelbottom=False)

# ax_scatter.xaxis.set_tick_params(direction='out', color='black', labelsize=12)# ax_scatter.yaxis.set_tick_params(direction='out', color='black', labelsize=12)# 以上两行代码等同于下面一句代码ax_scatter.tick_params(direction='out', color='black')

# 设置坐标轴字体for ax in [ax_topbar, ax_scatter, ax_rightbar]:for tick in ax.yaxis.get_majorticklabels():        tick.set_fontproperties(ticks_font)for tick in ax.xaxis.get_majorticklabels():        tick.set_fontproperties(ticks_font)

# s参数用于设置散点大小,c用于设置cmapax_scatter.scatter(x, y, s=np.abs(x / y) * 10, c=np.abs(x * y) * 0.02, alpha=0.6)

ax_topbar.hist(x, bins=np.linspace(np.min(x), np.max(x), 16), color='#2C5784')ax_rightbar.hist(y, bins=np.linspace(np.min(y), np.max(y), 16), orientation='horizontal', color='#20866C')plt.show()

绘制结果如下图所示:

带标注的函数图像

  
# 生成数据x = np.linspace(-4, 4, 1000)y1 = np.sin(x)y2 = np.cos(x)y3 = np.exp(x)

from matplotlib.font_manager import FontPropertieslabel_font = FontProperties(family='Times New Roman', size=18, weight='bold', style='normal')title_font = FontProperties(family='Times New Roman', size=20, weight='bold', style='normal')ticks_font = FontProperties(family='Times New Roman', size=12, weight='bold', style='normal')legend_font = FontProperties(family='Times New Roman', size=18, weight='bold', style='normal')fig, ax = plt.subplots(figsize=(8, 10), dpi=100, ncols=1, nrows=2)

# 绘制函数图像ax[0].plot(x, y1, color='red')ax[0].plot(x, y2, color='orange')ax[1].plot(x, y3, color='blue')# ax1和ax共享x轴,当需要在同一个图表中显示比例不同的图形时使用,比如exp(x)和sin(x)# ax1 = ax.twinx()

# --------------------------------------- Fig 1 --------------------------------------- ## 设置标题,坐标轴标签ax[0].set_title(r'$y=sin(x)$', fontproperties=title_font, color='black', pad=10)# ax[0].set_xlabel(r'$x$', fontproperties=label_font, color='black', ha='right')# ax[0].set_ylabel(r'$y$', fontproperties=label_font, color='black')# ax[0].xaxis.set_label_coords(5, 0)# ax[0].xaxis.set_label_coords(0, 1.5)

# 不显示右坐标轴和上坐标轴ax[0].spines['top'].set_visible(False)ax[0].spines['right'].set_visible(False)

# 移动左坐标轴和底部坐标轴到图形中间位置ax[0].spines['left'].set_position('center')ax[0].spines['bottom'].set_position('center')

# 设置x轴刻度# ax[0].xaxis.set_ticks_position('left')# 设置x轴刻度坐标ax[0].set_xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi])# 设置x轴刻度标签ax[0].set_xticklabels([r'$-\pi$', r'$-\frac{\pi}{2}$', r'$0$', r'$\frac{\pi}{2}$', r'$\pi$'])

# 设置y轴刻度ax[0].set_yticks([-1, 0, 1])

# 设置y轴刻度的位置ax[0].yaxis.set_ticks_position('left')

# ax[0].lines[1].set_linestyle('--')

# annotate函数的详细参数解释可以参考:# https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.axes.Axes.annotate.html"""annotate(text, xy, xytext, xycoords, textcoords, arrowprops ,*args, **kwargs)    text(string): 需要标注的文本    xy(tuple -> (float, float)): 标注的点/位置    xytext(tuple -> (float, float)): 放置标注文本的位置    textcoords(string): 给定xytext的坐标系统,可选('offset points', 'offset pixel')    xycoords(string): 给定xy的坐标系,默认'data',表示使用待标注对象的坐标系统    fontproperties(FontProperties): 需要标注的文本    arrowprops(dict): 设置标注文本和标注点之间的连接方式。arrowstyle="->" 表示使用箭头连接,    connectionstyle="arc3,rad=.6" 表示连接类型为圆弧, 半径为0.6"""

ax[0].annotate(r'$Sin(\frac{2\pi}{3}) = \frac{\sqrt{3}}{2}$', xy=(np.pi * 2 / 3, np.sqrt(3)/2), xycoords='data', xytext=(10, 30), \               textcoords='offset points', arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=.6"), fontproperties=ticks_font)

# 这里坐标轴标签是使用注记来设置的ax[0].annotate(r'$X$', xy=(4.4, 0), xycoords='data', color='black', fontproperties=label_font)

ax[0].annotate(r'$Cos(\frac{2\pi}{3}) = -\frac{1}{2}$', xy=(np.pi * 2 / 3, -1/2), xycoords='data', xytext=(-100, -30), \               textcoords='offset points', arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=.2"), fontproperties=ticks_font)

ax[0].annotate(r'$Y$', xy=(-0.3, 1.05), xycoords='data', color='black', fontproperties=label_font)

# 标记特定位置ax[0].scatter([2*np.pi/3, ], [-1/2,], color='orange', s=40)ax[0].plot([2*np.pi/3, 2*np.pi/3], [0, -1/2], linestyle='--', color='orange')ax[0].scatter([2*np.pi/3, ], [np.sqrt(3)/2,], color='red', s=40)ax[0].plot([2*np.pi/3, 2*np.pi/3], [0, np.sqrt(3)/2], linestyle='--', color='red')

# 设置图例ax[0].legend([r'$Sin(x)$', r'$Cos(x)$',], loc='best', prop=legend_font, shadow=False, facecolor='white')

# --------------------------------------- Fig 2 --------------------------------------- #ax[1].spines['top'].set_visible(False)ax[1].spines['right'].set_visible(False)

# 统一设置刻度标签字体for sub_ax in ax:for tick in sub_ax.xaxis.get_majorticklabels():        tick.set_fontproperties(ticks_font)

for tick in sub_ax.yaxis.get_majorticklabels():        tick.set_fontproperties(ticks_font)

ax[1].annotate(r'$X$', xy=(4.4, -0.7), xycoords='data', color='black', fontproperties=label_font)ax[1].annotate(r'$Y$', xy=(-4.4, 56), xycoords='data', color='black', fontproperties=label_font)

# 填充图像和坐标轴之间的图形# 如果要在x方向上的曲线之间填充,可以使用fill_betweenxax[1].fill_between(x, y3, 0, color='green')

# 使用tighe_layout可以自动调整子图参数,以使子图适合图形区域。fig.tight_layout()plt.show()

热力图(Heatmap)

  

# Heatmap

from mpl_toolkits.axes_grid1 import make_axes_locatable, axes_sizefrom matplotlib.font_manager import FontProperties

label_font = FontProperties(family='Times New Roman', size=18, weight='bold', style='normal')title_font = FontProperties(family='Times New Roman', size=20, weight='bold', style='normal')ticks_font = FontProperties(family='Times New Roman', size=12, weight='bold', style='normal')legend_font = FontProperties(family='Times New Roman', size=18, weight='bold', style='normal')

vegetables = ["cucumber", "tomato", "lettuce", "asparagus","potato", "wheat", "barley"]farmers = ["Farmer Joe", "Upland Bros.", "Smith Gardening","Agrifun", "Organiculture", "BioGoods Ltd.", "Cornylee Corp."]

harvest = np.array([[0.8, 2.4, 2.5, 3.9, 0.0, 4.0, 0.0],                    [2.4, 0.0, 4.0, 1.0, 2.7, 0.0, 0.0],                    [1.1, 2.4, 0.8, 4.3, 1.9, 4.4, 0.0],                    [0.6, 0.0, 0.3, 0.0, 3.1, 0.0, 0.0],                    [0.7, 1.7, 0.6, 2.6, 2.2, 6.2, 0.0],                    [1.3, 1.2, 0.0, 0.0, 0.0, 3.2, 5.1],                    [0.1, 2.0, 0.0, 1.4, 0.0, 1.9, 6.3]])

fig_size=8fig, ax = plt.subplots(figsize=(fig_size, fig_size), dpi=100)

# 使用matplotlib3.1.1绘制,会出现heatmap显示不全的问题# 这里使用的是matplotlib3.1.0im = ax.imshow(harvest, cmap=plt.cm.GnBu_r)

ax.set_xticks(np.arange(len(farmers)))ax.set_yticks(np.arange(len(vegetables)))

# ha -> horizontal align# va -> vertical alignax.set_xticklabels(farmers, ha='right', va='bottom', rotation_mode="anchor")ax.set_yticklabels(vegetables)

for tick in ax.xaxis.get_majorticklabels():    tick.set_rotation(45)    tick.set_fontproperties(ticks_font)

for tick in ax.yaxis.get_majorticklabels():    tick.set_fontproperties(ticks_font)

for i in range(len(vegetables)):    for j in range(len(farmers)):        text = ax.text(j, i, harvest[i, j],                       ha="center", va="center", color="w", fontproperties=ticks_font)

# 参数的设置我暂时也不太理解,可以参考:# https://stackoverflow.com/questions/18195758/set-matplotlib-colorbar-size-to-match-graph

# 创建颜色条,colorbar可以理解为子图,即sub figcbar = fig.colorbar(im, orientation='vertical', fraction=0.046, pad=0.04)

# colorbar.ax可以看做是一个fig中的axes,具有axes的所有属性和方法

# 设置颜色条的刻度标签cbar.ax.set_yticklabels(np.arange(0, 7), fontproperties=ticks_font)

# 设置颜色条坐标轴字体# https://stackoverflow.com/questions/15908371/matplotlib-colorbars-and-its-text-labelscbar.ax.set_ylabel('Color Bar', fontproperties=title_font, rotation=270, labelpad=16)

# 设置标题字体ax.set_title("Harvest of local farmers (in tons/year)", fontproperties=title_font, pad=10)fig.tight_layout()plt.show()

绘制结果如下所示:


总结

以上的几种图形基本上按照了以下步骤进行绘制:

  1. 定义字体(比如图表标题、坐标轴标题、刻度数字以及图例等)
  2. 创建 axes(plt.axes()、plt.subplots()或者fig.add_subplot() )
  3. 设置 fig 的属性(比如背景颜色等)
  4. 使用 axes 设置轴(Spine)的属性(包括显示范围、颜色、字体以及刻度等)
  5. 使用 axes 绘制图形
  6. 使用 axes 设置线的属性(比如线型、颜色以及粗细等等)
  7. 使用 axes 设置标题以及图例

本文主要介绍了 matplotlib 绘图对象中 fig 和 axes 的差异,可以这样理解,fig 是画板,而 axes 是画板上的图形,一个 fig 中可以包含多个 axes,而 axes 才是控制绘图的关键。
其次通过几种常用图形的绘制,介绍了 matplotlib 绘图过程中大部分的常用操作。以上所有图形的绘制均使用了同一种方式,即利用 axes 来进行绘图,主要有两个原因,其一,这样写的代码可读性比较好,比较容易修改(至少个人认为是这样的)。其二,这种方式可以实现对图表的任意部件进行自定义的修改。我虽然都使用了 axes 来绘图,并且也推荐使用这种方式来进行绘图。但并不意味着你也要使用这种方式,如果只是绘制一些示意图,对图形并没有太多控制,其实 plt.plot()可能更方便,这也是 matplotlib 默认的方式。


Reference

https://matplotlib.org/tutorials/introductory/usage.htmlhttps://matplotlib.org/1.5.1/faq/usage_faq.html#parts-of-a-figurehttps://zhuanlan.zhihu.com/p/93423829https://matplotlib.org/3.1.3https://stackoverflow.com/questions/18195758


- END -

matplotlib xticks 基于 旋转_数据可视化之 matplotlib 绘图篇相关推荐

  1. matplotlib xticks 基于 旋转_咬文嚼字——对matplotlib的文字绘图总结

    / 导读 / 我们经常面临在画图时的文字标注,本文从图片.坐标轴.坐标值等层面讲起,对matplotlib的文字绘图功能进行总结说明. Figure和Axes上的文本 Matplotlib具有广泛的文 ...

  2. python数据可视化的包怎么安装_数据可视化包 - matplotlib

    Matplotlib 1,Matplotlib - 介绍 Matplotlib是一个强大的Python绘图和数据可视化的工具包. # 安装方法 pip install matplotlib # 引用方 ...

  3. python的数据可视化库_数据可视化库--Matplotlib

    折线图 import pandas as pd unrate = pd.read_csv('unrate.csv') unrate['DATE'] = pd.to_datetime(unrate['D ...

  4. 数据可视化总结——matplotlib、seaborn

    数据可视化总结--matplotlib.seaborn 导包 matplotlib基本参数 折线图 绘制直方图 hist(), plt.bar() 绘制水平方向的柱状图 饼图 散点图 箱线图 seab ...

  5. 【数据可视化】Matplotlib 入门到精通学习笔记(超详细)

    数据可视化是什么 如果将文本数据与图表数据相比较,人类的思维模式更适合于理解后者,原因在于图表数据更加直观且形象化,它对于人类视觉的冲击更强,这种使用图表来表示数据的方法被叫做数据可视化. 当使用图表 ...

  6. python绘制不带颜色曲线图_Python数据可视化库-Matplotlib——折线图,子图绘制

    # coding:utf-8 import pandas as pd import numpy as np from matplotlib import pylab as plt # 导入数据可视化库 ...

  7. 数据图表可视化_数据可视化如何选择正确的图表第1部分

    数据图表可视化 According to the World Economic Forum, the world produces 2.5 quintillion bytes of data ever ...

  8. 《Python数据可视化之matplotlib实践》配套代码

    向AI转型的程序员都关注了这个号???????????? 机器学习AI算法工程   公众号:datayx <Python数据可视化之matplotlib实践> 借助matplotlib讲解 ...

  9. [转载] Python数据可视化库-Matplotlib——折线图绘制

    参考链接: Python Matplotlib数据可视化 plot折线图 # coding:utf-8 import pandas as pd import numpy as np from matp ...

最新文章

  1. nginx php 大小写问题,Nginx实现url请求不区分大小写
  2. 生命简史——跨越地球40亿年
  3. C++中左移操作符的重载
  4. linux命令冒号加叹号,Linux中的叹号命令
  5. 【行业】点餐App未来必须面对的三大难题
  6. 【nodejs笔记3】Express基本用法,和路由控制,和模板渲染ejs
  7. fifo的rdata_同步FIFO设计
  8. sap.m.list render initialization process
  9. 苹果电脑删除软件_软件自动开启很烦人?如何彻底关掉开机自动开启的应用程序...
  10. 循环卷积和周期卷积的关系_基于单口RAM读写的卷积电路(下)
  11. 使用Typescript和React的最佳实践
  12. 专访死马:为什么说Egg.js是企业级Node框架
  13. idea 报 Cannot access alimaven
  14. 老李分享:Android性能优化之内存泄漏3
  15. 光储并网VSG系统Matlab/simulink仿真模型 系统前级直流部分包括光伏阵列、变换器、储能系统和双向dcdc变换器,后级交流子系统包括逆变器LC滤波器,交流负载
  16. xp系统打印机服务器win7连接不了,Win7无法共享xp打印机的解决方法
  17. 机器学习——马氏距离
  18. POND:高效的 Python 通用对象池库
  19. MIMIC-IV-v2.0安装教程
  20. DHCP Relay

热门文章

  1. 在Html中使用Requirejs进行模块化开发
  2. Spring基于 Annotation 的简单介绍
  3. hdu 1087 Super Jumping! Jumping! Jumping!
  4. C# WinForm开发系列 - DataGridView A
  5. nginx+fastcgi+c/c++搭建高性能Web框架
  6. 继承属性public private
  7. 台湾国立大学郭彦甫Matlab教程笔记(20) root finding(numeric)
  8. MFC中滚动条slider和编辑框edit的联动
  9. leetcode 454. 四数相加 II c语言
  10. mysql判断是否建立索引_判断mysql中列是否要添加索引的标准