在不完整/未填充的行中将matplotlib图例条目居中? [英] Centering matplotlib legend entries within incomplete/unfilled rows?

查看:241
本文介绍了在不完整/未填充的行中将matplotlib图例条目居中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我要制作一个包含五个项目的地块,并且只有空间来创建具有3列的图例(比这太宽了,列数太多了),例如

Say I'm making a plot with five items, and only have room to create a legend with 3 columns (more columns than this would be too wide), e.g.

import matplotlib.pyplot as plt
f, a = plt.subplots()
for i in range(5):
    a.plot(np.arange(10),np.random.rand(10),label='Item #%d'%i)
a.legend(ncol=3)

底部一行的后两个条目为左对齐,在右侧留下了一个很大的空白空间,这在美学上并不十分令人满意.当您必须标记大量行时,这尤其成问题.

The trailing two entries in the bottom row are left-aligned, leaving a big empty space on the right that isn't very aesthetically pleasing. This becomes especially problematic when you have to label very large numbers of lines.

有什么办法可以使未填充行中的条目居中?

Is there any way to center the entries within the unfilled row?

推荐答案

matplotlib图例是基于列的.您不能有跨越多个列的图例条目.也就是说,当然可以在图例中具有奇数行的奇数"个条目居中,而在图例中具有偶数行的偶"个奇数条目,也可以类似地居中".这可以通过在外部位置使用空艺术家来完成.

The matplotlib legend is column-based. You cannot have legend entries spanning multiple columns. That said, it is of course possible to "center" an odd number of entries in a legend with an odd number of rows and similarly "center" an even number of entries in a legend with an even number of rows. This would be done by using empty artists at the outer positions.

import matplotlib.pyplot as plt
import numpy as np

ncols = 3  # or 4
nlines = 7 # or 10

x = np.linspace(0,19)
f = lambda x,p: np.sin(x*p)
h = [plt.plot(x,f(x,i/10.), label="Line {}".format(i))[0] for i in range(nlines)]
h.insert(nlines//ncols, plt.plot([],[],color=(0,0,0,0), label=" ")[0])
plt.legend(handles=h, ncol=ncols, framealpha=1)

plt.show()

如果列数为奇数,图例条目的数为偶数,反之亦然,则上述操作是不可能的.一种选择是使用两个不同的图例并将它们放置在另一个图例的下方,以使最后一行的条目看起来居中.

If the number of columns is odd and the number of legend entries is even or vice versa the above is not possible. An option may be to use two different legends and position them below one another such that it looks like the entries of the last line are centered.

import matplotlib.pyplot as plt
import numpy as np

ncols = 3
nlines = 8

x = np.linspace(0,19)
f = lambda x,p: np.sin(x*p)
h = [plt.plot(x,f(x,i/10.), label="Line {}".format(i))[0] for i in range(nlines)]

kw = dict(framealpha=1, borderaxespad=0, bbox_to_anchor=(0.5,0.2), edgecolor="w")
leg1 = plt.legend(handles=h[:nlines//ncols*ncols], ncol=ncols, loc="lower center", **kw)
plt.gca().add_artist(leg1)
leg2 = plt.legend(handles=h[nlines//ncols*ncols:], ncol=nlines-nlines//ncols*ncols, 
                   loc="upper center", **kw)

plt.show()

这里的缺点是图例没有边框,并且两个图例都需要单独放置.为了克服这个问题,需要更深入地研究并使用图例的一些私有属性(注意,这些内容可能会因版本而异,恕不另行通知).
然后,该想法可以是删除创建后的第二个图例,并使其_legend_handle_box放入第一个图例中.

The drawback here is that the legend has no border and both legends need to be positionned individually. To overcome this one would need to dig a little deeper and use some private attributed of the legend (caution, those may change from version to version without notice).
The idea can then be to remove the second legend once created and get its _legend_handle_box to place into the first legend.

import matplotlib.pyplot as plt
import numpy as np

ncols = 3
nlines = 8

x = np.linspace(0,19)
f = lambda x,p: np.sin(x*p)
h = [plt.plot(x,f(x,i/10.), label="Line {}".format(i))[0] for i in range(nlines)]

kw = dict(framealpha=1, bbox_to_anchor=(0.5,0.2))
leg1 = plt.legend(handles=h[:nlines//ncols*ncols], ncol=ncols, loc="lower center", **kw)
plt.gca().add_artist(leg1)
leg2 = plt.legend(handles=h[nlines//ncols*ncols:], ncol=nlines-nlines//ncols*ncols)

leg2.remove()
leg1._legend_box._children.append(leg2._legend_handle_box)
leg1._legend_box.stale = True

plt.show()

这篇关于在不完整/未填充的行中将matplotlib图例条目居中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆