欢迎大家订阅《Python实战-构建基于股票的量化交易系统》小册子,小册子会陆续推出与小册内容相关的专栏文章,对涉及到的知识点进行更全面的扩展介绍。
本次专栏主要介绍下小册子中使用Matplotlib库时所涉及到的一些问题。最常见的是“中文显示乱码问题”和“tight_layout()出错问题”。
中文显示乱码问题
由于Matplotlib库缺少中文字体,因此在图表上显示中文时会出现乱码。一种解决方法为在代码中添加以下参数设置,如下所示:
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.figure import Figure
# 正常显示画图时出现的中文和负号
from pylab import mpl
mpl.rcParams['font.sans-serif']=['SimHei']
mpl.rcParams['axes.unicode_minus']=False
# 以下是其他代码
另一种方法是更改配置文件。这里我们以mac系统为例来介绍下。在MAC中调试matplotlib时中文显示框框解决方法:
-
下载simhei.ttf字体库拷贝至matplotlib字体文件夹(Macintosh HD ▸ 用户 ▸ xxxx ▸ anaconda3 ▸ lib ▸ python3.7 ▸ site-packages ▸ matplotlib ▸ mpl-data ▸ fonts▸ ttf)。
-
同样在matplotlib/mpl-data/fonts目录下面修改配置文件matplotlibrc
font.family : sans-serif
font.sans-serif : SimHei, Bitstream Vera Sans, Lucida Grande, Verdana, Geneva, Lucid, Arial, Helvetica, Avant Garde, sans-serif axes.unicode_minus:False
- 3、在Python中运行如下代码重新加载字体使配置生效:
from matplotlib.font_manager import _rebuild
_rebuild() #reload
tight_layout()出错问题
在matplotlib中,轴Axes的位置以标准化图形坐标指定,可能发生的情况是轴标签、标题、刻度标签等等会超出图形区域,导致显示不全。Matplotlib v1.1 引入了一个新的命令tight_layout(),作用是自动调整子图参数,使之填充整个图像区域。 调用plt.show()函数时会自动运行tight_layout()函数,如下所示:
def show(self):
self.figure.tight_layout()
FigureCanvasAgg.draw(self)
if PORT is None:
return
if matplotlib.__version__ < '1.2':
buffer = self.tostring_rgb(0, 0)
else:
buffer = self.tostring_rgb()
if len(set(buffer)) <= 1:
# do not plot empty
return
render = self.get_renderer()
width = int(render.width)
plot_index = index if os.getenv("PYCHARM_MATPLOTLIB_INTERACTIVE", False) else -1
try:
sock = socket.socket()
sock.connect((HOST, PORT))
sock.send(struct.pack('>i', width))
sock.send(struct.pack('>i', plot_index))
sock.send(struct.pack('>i', len(buffer)))
sock.send(buffer)
except OSError as _:
# nothing bad. It just means, that our tool window doesn't run yet
pass
我们通过以下一个例程来介绍,最终的显示效果如下所示:
fig = plt.figure(figsize=(12, 8))
ax1 = fig.add_subplot(211)
ax2 = fig.add_subplot(212)
ax1.plot(np.arange(10), np.random.randint(0, 10, 10), ls='-', c='r', lw=1)
ax2.plot(np.arange(10), np.random.randint(10, 20, 10), ls='-', c='y', lw=1)
plt.show()

不过很多时候会出现tight_layout()不工作的情况,比如出现以下提示:
UserWarning: This figure includes Axes that are not compatible with tight_layout, so results might be incorrect. warnings.warn("This figure includes Axes that are not compatible "
这个警告的原因是tight_layout这个函数出错了,警告语句出现的原因时axes列表为空,tight_layout()中相应的代码,如下所示:
subplotspec_list = get_subplotspec_list(self.axes)
if None in subplotspec_list:
cbook._warn_external("This figure includes Axes that are not "
"compatible with tight_layout, so results "
"might be incorrect.")
可见这个函数并不太稳定。tight_layout不起作用的时候,绘图效果如下所示,可见子图并没有填充整个图像区域。

网上搜索了下发现也有类似的情况出现,附上部分案例的截图:

接下来我们尝试下解决方法,tight_layout在plt.savefig的调用方式相对比较稳定,我们将plt.show()函数替换为plt.savefig函数,替换后会在本地另外为png图片,该图片中子图填充了整个图像区域。
plt.savefig('fig.png', bbox_inches='tight') # 替换 plt.show()
购买小册子的同学注意了:我们会把这篇专栏的链家附加到《前置基础:Matplotlib函数式绘图的方式》这一节内容中。
更多的量化交易内容欢迎大家订阅小册阅读!!同时也欢迎大家关注我的微信公众号【元宵大师带你用Python量化交易】了解更多Python量化交易相关内容