Matplotlib hatch color和edgecolor的解耦方法 [Decouple the hatch color and the edgecolor in a bar figure]

plt.bar

matplotlib.pyplot.bar

用matplotlib画bar图是可以给柱子加花纹的,叫做hatch,指定hatch参数就可以。但是有一个问题,hatch的颜色默认是跟edgecolor一致的,其中edgecolor也是一个参数,可以指定柱子边框的颜色。hatch的颜色没有一个参数可以单独指定。

这会造成一些麻烦以及不灵活。比如我就是想用黑色的柱子边框,但是花纹并不想用黑色的。那怎么办呢?前人有一些方法:

How to decouple hatch and edge color in matplotlib?

这个答主是通过画两层柱子实现,底下的一层指定hatch和你喜欢的hatch颜色(设置edgecolor),上面的一层只画一个透明的黑色边框柱子(设置edgecolor为黑色)。画出来的图就可以满足要求。

但是问题来了。用这种方法画出来的柱子,本质上是两根柱子,如果你要画legend,你的legend要么就是有花纹而且跟花纹同色的边框,要么就是透明黑框。也就是说,你没有办法画一个跟柱子一模一样的legend。

勉强让人能接受的做法就是——放弃legend的黑框。legend没有黑框也没有关系对吧,小问题。要不然就不要画hatch咯。

那有没有一种灵活的办法呢?不好意思,官方说没有。

There is no direct API level control of the hatch color or linewidth.
Changes to the default style

那强迫症只能自己动手了。matplotlib相关的源代码是在

matplotlib/lib/matplotlib/patches.py

定位一下相关代码

可见逻辑是设置默认的self._hatch_colormpl.rcParams['hatch.color']。然后如果设置了edgecolor参数就会调用self.set_edgecolor(edgecolor)更新参数。

可以最终将问题定位在self._set_edgecolor()这个函数里面。逻辑是如果不设定edgecolor,那他就会去找mpl.rcParams里面的默认参数,默认参数都没有的话就不改变self._hatch_color(也就是说依然是默认的mpl.rcParams['hatch.color'])。

如果设置了edgecolor,那他就把self._hatch_color也设置成self._edgecolor。这就是为什么默认hatch的颜色默认是跟edgecolor一致的。

我用了一种笨拙的方法去单独设置self._hatch_color,因为没有时间去折腾一个更优雅的方法。

对…只是直接把默认赋值给注释掉,然后画bar图之前设置mpl.rcParams['hatch.color']作为hatch颜色就好啦。

e.g.

Done.

Leave a Comment