因为物理实验作图的原因,我有幸接触了 matplotlib ,配合 scipy 的其他组件,可以完成我所有需要的任务(我的需求都是非常初级的 :-) )。鉴于接下来可能转战 R ,所以特地把最近 matplotlib 的使用经验总结一下。

import

import numpy as np
from pylab import *
from scipy.optimize import leastsq
from matplotlib.font_manager import FontManager

简单的绘图

# 折线图:
plot(x, y)
plot(x, y, '-')
plot(x, y, '-', linewidth=2)

# 散点图
plot(x, y, 'o', markersize=2)
plot(x, y, ',')

最小二乘法拟合

# 拟合函数
def fun(x, p):
    k, b = p
    return k * x + b

# 差值
def err(p, x, y):
    return fun(x, p) - y


# 最小二乘法 [1,1] 为初始的猜测
sq = leastsq(err, [1,1], args=(x, y))

numpy 常用函数

# 把 list 转为 np.array
np.array([1, 2, 3, 4, 5])

# 类似于 range 每隔 interval 生成 [beg, end) 的一个值
np.arange(beg, end, interval)

# 把 [beg, end] 均分为 count 段,默认包含右端点
np.linspace(beg, end, count, endpoint=True)

# np.array 可以直接进行向量化操作
x = np.array([...])
y = np.array([...])
x + y
x - y
x * y
x / y
x ** 2
np.sin(x)
np.sqrt(x)

设置绘制区域及坐标轴样式

# 绘制区域
xlim(-0.020, 0.200)
ylim(-10, 90)

# 只显示两条坐标轴
ax = gca()
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.spines['bottom'].set_position('zero')
ax.spines['left'].set_position('zero')
ax.xaxis.set_ticks_position('bottom')
ax.yaxis.set_ticks_position('left')

# 坐标轴名称
xlabel(r"$t \mathrm{(ms)}$")
ylabel(r"$L \mathrm{(mm)}$")

# 设置坐标轴刻度
xticks_list = np.linspace(-0.020, 0.200, 12)
xticks(xticks_list, ['%.2f' % x for x in xticks_list])
yticks_list = np.linspace(-10, 90, 11)
yticks(yticks_list, ['%.0f' % y for y in yticks_list])

# 显示网格
grid(True)
# 另外一种设置方法
fig, ax = subplots()
ax.set_title(r'$\Delta T = 0.01\mathrm{(ms)},\ l = %d\mathrm{m},\ g = %.2f\mathrm{m/s}$' % (l, g))
y_range = np.linspace(rad(-90), rad(90), 13)
ax.set_yticks(y_range)
ax.set_yticklabels([r'$%.0f^{\circ}$' % deg(y) for y in y_range])
ax.set_ylim(-rad(100), rad(100))
ax.set_ylabel(r'$\theta$')
ax.set_xlabel(r'$t\mathrm{(s)}$')

中文文本框

# 中文字体
myfont = matplotlib.font_manager.FontProperties(fname='/Library/Fonts/AdobeSongStd-Light.otf')

#相关系数
corr = np.corrcoef(x, y)[0][1]

# 文本框
bbox_props = dict(boxstyle="square", fc="white", ec="black", lw=2)

# 文本
text1 = "$y=ax+b$\n$a=%.6f$\n$b=%.6f$\n$r=%.6f$" % (sq[0][0], sq[0][1], corr)
ax.text(x0, y0, text1, ha="left", va="center", size=15, bbox=bbox_props)

显示及输出图片

# 预览图片
show()

# 保存图片
savefig('/Users/abcdabcd987/Desktop/figure_1.png', dpi=300) 

# 清除图像 释放内存
clf() 

标题及图示

# 设置标题
ax.set_title('title')

# plot 设置 label
ax.plot(x, y, '.', label='My Label')

# 显示图示
ax.legend(loc='upper center', prop={'size': 9})

常用绘图功能

# 指定 (r,g,b,a) 颜色
plot(x, y, color=(1, 1, 1, 1))

# 对数坐标
ax.set_yscale('log')

# 极坐标
subplot(polar=True)
plot(x, y)

# 双y轴
fig, ax1 = subplots()
ax1.set_title(r'$\theta = %d^{\circ},\ l = %d\mathrm{m},\ g = %.2f\mathrm{m/s},\ T = %.2f\mathrm{s}$' % (90, l, g, T))
ax1.set_xscale('log')
ax1.set_xlabel(r'$\Delta T\mathrm{(s)}$')

ax1.set_yscale('log')
ax1.set_ylabel('Standard Error')
plot1 = ax1.plot(deltaTs, stds, 'bo', markersize=6, label='Standard Error')

ax2 = twinx()
ax2.set_yscale('log')
ax2.set_ylabel('Calculation Time (s)')
plot2 = ax2.plot(deltaTs, times, 'gs', markersize=6, label='Calculation Time (s)')

plots = plot1 + plot2
plot_labels = [p.get_label() for p in plots]
ax1.legend(plots, plot_labels, loc='upper center', prop={'size': 9})

参考资料