matplotlib绘图实例

感觉matplotlib还是比gnuplot等要好用一些。虽然以后并非一定不用gnuplot画图,但目前还是优先把matplotlib搞熟练。不过说实话,画图这事情其实不难。麻烦的是画出想要的各种样式的细节。所以我是一方面熟练用matplotlib画出图,另一方面也是想整理出一些习惯的样式。因为我有点想重复造个轮子(不是),写一个Fortran调用Python绘图的库。方便我的程序计算完成后直接绘出图,并且可以相对自动化地调整所需的样式。所以在这里整理一些常用的解决方案。

函数图像

import numpy as np
import matplotlib.pyplot as plt

def func(x):
  return np.exp(-np.sqrt(x))

x = np.linspace(1, 5, 81)
# x = np.arange(1, 5.05, 0.05)

fig, ax = plt.subplots()
ax.plot(x, func(x), '-', label='exp(-sqrt(x))')
plt.legend()
plt.show()


插值

import numpy as np
from scipy import interpolate
import matplotlib.pyplot as plt

# input data (x, y)
x = np.linspace(0, 2, 6)
y = np.exp(-x**2)

f = interpolate.interp1d(x, y, kind='cubic')
x_new = np.linspace(0, 2, 21)
y_new = f(x_new)

fig, ax = plt.subplots()
ax.plot(x, y, 'ro')
ax.plot(x_new, y_new, 'b-')
plt.show()

拟合

import numpy as np
from scipy import optimize
import matplotlib.pyplot as plt

def func(x, a, b, c):
  return a*np.exp(-b*x**2) + c

x = np.linspace(0, 2, 11)
noise = 0.05 * np.random.normal(size=11) 
y = np.exp(-x**2) + noise

popt, pcov = optimize.curve_fit(func, x, y)
# popt = array([ 1.06192427,  0.77611601, -0.07407258])
x_new = np.linspace(0, 2, 21)
y_new = func(x_new, *popt)

fig, ax = plt.subplots()
ax.plot(x, y, 'ro')
ax.plot(x_new, y_new, 'b-')
plt.show()

对数坐标

import numpy as np
import matplotlib.pyplot as plt

def func(x):
  return np.exp(np.sqrt(x))

x = np.linspace(0, 10, 101)

fig, ax = plt.subplots()
ax.plot(x, func(x), '-')
ax.set_yscale('log')
plt.show()
# user-define scale
# def forward(x):
#   return ***
#
# def inverse(x):
#   return ***
#
# ax.set_yscale('function', functions=(forward, inverse))

共用坐标轴

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(0, 5.01, 0.01)
fig, (ax1, ax2) = plt.subplots(nrows=2, ncols=1, sharex=True)
fig.subplots_adjust(hspace=0)

ax1.plot(x, np.sqrt(x), 'r-', label='sqrt')
ax1.legend()
ax2.plot(x, np.log(x), 'b-', label='ln')
ax2.legend()
plt.show()

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(0, 5.01, 0.01)
fig, (ax1, ax2) = plt.subplots(2, sharex=True, gridspec_kw={'hspace': 0})

ax1.plot(x, np.sqrt(x), 'r-', label='sqrt')
ax1.set_zorder(20) # key point 
ax1.legend()
ax2.plot(x, np.log(x), 'b-', label='ln')
ax2.set_zorder(10) # key point 
ax2.legend()
plt.show()

截断坐标轴

# reference: https://matplotlib.org/gallery/subplots_axes_and_figures/broken_axis.html
import numpy as np
import matplotlib.pyplot as plt

y = np.linspace(0, 20, 401)
x = np.exp(-y) * np.cos(10*y)

fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True, gridspec_kw={'hspace': 0.05})
ax1.plot(x, y, '-')
ax2.plot(x, y, '-')

ax1.set_ylim(17.7, 20)  # outliers only
ax2.set_ylim(0, 8.5)

ax1.spines['bottom'].set_visible(False)
ax2.spines['top'].set_visible(False)
ax1.tick_params(bottom=False, labelbottom=False)

d = .01  # how big to make the diagonal lines in axes coordinates
# arguments to pass to plot, just so we don't keep repeating them
kwargs = dict(transform=ax1.transAxes, color='k', linewidth=0.5, clip_on=False)
ax1.plot((-d, +d), (-d, +d), **kwargs)        # top-left diagonal
ax1.plot((1 - d, 1 + d), (-d, +d), **kwargs)  # top-right diagonal

kwargs.update(transform=ax2.transAxes)  # switch to the bottom axes
ax2.plot((-d, +d), (1 - d, 1 + d), **kwargs)  # bottom-left diagonal
ax2.plot((1 - d, 1 + d), (1 - d, 1 + d), **kwargs)  # bottom-right diagonal

plt.show()

三维表面图

import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm

x = np.linspace(-2, 2, 41)
y = np.linspace(-2, 2, 41)
X, Y = np.meshgrid(x, y)
Z = np.exp(-X**2) * np.exp(-Y**2)

fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(X, Y, Z, cmap=cm.jet, linewidth=0, antialiased=False)
fig.colorbar(surf, shrink=0.2, aspect=5)
plt.show()

import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm

x = np.linspace(-2, 2, 41)
y = np.linspace(-2, 2, 41)
X, Y = np.meshgrid(x, y)
Z = np.exp(-X**2-Y**2)
# adjust data range
ulim = 1.
llim = 0.
error = 5e-4
Z[np.where(np.abs(Z-ulim)<error)] = ulim
Z[np.where(np.abs(Z-llim)<error)] = llim

x_ticks = np.array([-2,-1,0,1,2])
y_ticks = np.array([-2,-1,0,1,2])
z_ticks = np.array([0,0.5,1])

fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(X, Y, Z, cmap=cm.jet, linewidth=0, antialiased=False)
ax.set_xticks(x_ticks)
ax.set_yticks(y_ticks)
ax.set_zticks(z_ticks)
# remove grid
ax.grid(b=False) 
# set pane color to be white
# https://stackoverflow.com/questions/11448972
ax.xaxis.set_pane_color((1.0, 1.0, 1.0, 1.0)) 
ax.yaxis.set_pane_color((1.0, 1.0, 1.0, 1.0))
ax.zaxis.set_pane_color((1.0, 1.0, 1.0, 1.0))
# https://stackoverflow.com/questions/48442713
ax.zaxis._axinfo['juggled'] = (1,2,0)
# inner ticks
# https://dawes.wordpress.com/2014/06/27/publication-ready-3d-figures-from-matplotlib/
ax.xaxis._axinfo['tick']['inward_factor'] = 0
ax.xaxis._axinfo['tick']['outward_factor'] = 0.4
ax.yaxis._axinfo['tick']['inward_factor'] = 0
ax.yaxis._axinfo['tick']['outward_factor'] = 0.4
ax.zaxis._axinfo['tick']['inward_factor'] = 0
ax.zaxis._axinfo['tick']['outward_factor'] = 0.4
ax.zaxis._axinfo['tick']['outward_factor'] = 0.4

ax.xaxis.set_rotate_label(False)
ax.yaxis.set_rotate_label(False)
ax.zaxis.set_rotate_label(False)
ax.set_proj_type('ortho')
ax.view_init(elev=45, azim=135)
# make z_ticks for colorbar valid
surf.set_clim([0, 1])
# draw colorbar, control position via pad option
cbar = fig.colorbar(surf, shrink=0.2, aspect=5, ticks=z_ticks, pad=-0.1)
# hide ticks in colorbar
cbar.ax.tick_params(size=0)

plt.show()

发表评论

电子邮件地址不会被公开。 必填项已用*标注