Matplotlib 作图相比于使用Origin这种商业软件更为程序化,当熟练了以后还是非常方便的。
参考官方文档以及一些教程,不难做出一些比较好看的散点、柱状图等,这些也是在学术研究中比较常见的chart。
但是,常常我们需要在柱状图或者散点图上增加一些图例以及标注以增加图表的可读性,那么该怎么做呢?此处介绍两处笔者用到的增加图例与标注的方法:

1
2
3
from matplotlib import pyplot as plt
plt.figure()
ax = plt.subplot(111) # ax = plt.add_subplot(111)

图例

图例比较简单,笔者主要参考这篇百度经验
在原来绘画的基础上,增加label属性。

1
2
sin, = ax.plot(x, y1, color='red', label='sin')
cos, = ax.plot(x, y2, color='blue', label='cos')

然后画出图例,并标出其位置:
1
ax.legend(loc='lower right')

loc即location, lower right即右下角,也可以是upper right等等
使用label参数会相对省事一点,也可以这么做
1
2
3
sin, = ax.plot(x, y1, color='red')
cos, = ax.plot(x, y2, color='blue')
ax.legend((sin,cos),('sin','cos'),loc='lower right')

更为复杂的图例可以参考这里
以及官方文档
比如想要把图例放到图的外面,则可以用 bbox_to_anchor 锚定图例的位置。下面是简短例子,具体可见官方文档。

1
2
3
4
5
# 下面方法可以将图例锚定在图的右边,`1.05, 1`表示锚定图的右上角(偏右一点),然后锚定点在图例的左上方
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0.)
# 下面方法是将图例锚定在图的左上方偏上一点点,且图例的宽和高分别是1和0.102,锚定点在图例的左下方。
plt.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc='lower left',
ncol=2, mode="expand", borderaxespad=0.)

标注

对于柱状图或者折线图可能需要对每个点进行标注,用到的是ax.text函数,在这里也安利一个Python库,叫adjust_text,这个工具的好处是可以不用考虑这些标注是否会遮挡图表的内容。

先说普通模式,比如柱状图:

1
2
3
4
5
6
7
8
x = [10,20,...]
y = [0.5,0.6,0.7...]
bars=ax.bar(x,y,color='green',tick_label=x,width=2)
for j,rect in enumerate(bars):
left = rect.get_x() # 得到这根柱子的横坐标(可以考虑向左位移)
# left,top: 得到柱子左上定点位置并产生个向上0.01的位移
top = rect.get_y() + rect.get_height() + 0.01
ax.text(left,top,'%.3f'%y[j]) # 标注柱子的“值”并且保留三位有效数字

如果用adjust_text,可以是:
1
2
3
4
5
6
7
8
9
x = [10,20,...]
y = [0.5,0.6,0.7,...]
bars=ax.bar(x,y,color='green',tick_label=x,width=2)
for j,rect in enumerate(bars):
left = rect.get_x()+1
top = rect.get_y()+rect.get_height()+0.01
texts.append(ax.text(left,top,'%.3f'%y[j]))
adjust_text(texts,autoalign='y', only_move={'points':'y', 'text':'y'},
force_points=0.5, expand_text=(1.2, 1.3), ha='center')

效果参考: https://github.com/Phlya/adjustText/blob/master/examples/Examples.ipynb
其中In[17]是笔者所作的图并被选为案例。adjust_text在原有的基础上对位置进行了稍微的调整,还允许repulsive point,用以人工干预微调。