如何将传说放在剧情之外
我有一系列20个情节(不是子情节)要在一个数字中制作。我希望这个传奇是开箱即用的。同时,我不想改变轴,因为图形的大小减小了。
- 我想将图例框保留在绘图区域之外(我希望图例位于绘图区域右侧的外部)。
- 有没有办法减小图例框内文本的字体大小,使图例框的大小变小?
我有一系列20个情节(不是子情节)要在一个数字中制作。我希望这个传奇是开箱即用的。同时,我不想改变轴,因为图形的大小减小了。
有很多方法可以做你想做的事。为了补充Christian Alis和Navi已经说过的内容,您可以使用关键字参数将图例部分放在轴外和/或减小字体大小。bbox_to_anchor
在考虑减小字体大小(这可能会使内容难以阅读)之前,请尝试将图例放在不同的位置:
因此,让我们从一个通用示例开始:
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(10)
fig = plt.figure()
ax = plt.subplot(111)
for i in xrange(5):
ax.plot(x, i * x, label='$y = %ix$' % i)
ax.legend()
plt.show()
如果我们做同样的事情,但使用关键字参数,我们可以将图例稍微移出轴边界:bbox_to_anchor
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(10)
fig = plt.figure()
ax = plt.subplot(111)
for i in xrange(5):
ax.plot(x, i * x, label='$y = %ix$' % i)
ax.legend(bbox_to_anchor=(1.1, 1.05))
plt.show()
同样,使图例更水平和/或将其放在图的顶部(我也打开了圆角和简单的投影):
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(10)
fig = plt.figure()
ax = plt.subplot(111)
for i in xrange(5):
line, = ax.plot(x, i * x, label='$y = %ix$'%i)
ax.legend(loc='upper center', bbox_to_anchor=(0.5, 1.05),
ncol=3, fancybox=True, shadow=True)
plt.show()
或者,缩小当前图的宽度,并将图例完全放在图轴之外(注意:如果使用tight_layout()
),则省略:ax.set_position()
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(10)
fig = plt.figure()
ax = plt.subplot(111)
for i in xrange(5):
ax.plot(x, i * x, label='$y = %ix$'%i)
# Shrink current axis by 20%
box = ax.get_position()
ax.set_position([box.x0, box.y0, box.width * 0.8, box.height])
# Put a legend to the right of the current axis
ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))
plt.show()
以类似的方式,垂直缩小绘图,并在底部放置一个水平图例:
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(10)
fig = plt.figure()
ax = plt.subplot(111)
for i in xrange(5):
line, = ax.plot(x, i * x, label='$y = %ix$'%i)
# Shrink current axis's height by 10% on the bottom
box = ax.get_position()
ax.set_position([box.x0, box.y0 + box.height * 0.1,
box.width, box.height * 0.9])
# Put a legend below current axis
ax.legend(loc='upper center', bbox_to_anchor=(0.5, -0.05),
fancybox=True, shadow=True, ncol=5)
plt.show()
看看matplotlib传奇指南。你也可以看看plt.figlegend()。
。
bbox_to_anchor
)图例位于轴的边界框内,使用参数 plt.legend
。
例如,将图例放在边界框的右上角,默认情况下,该边界框以轴坐标(或边界框表示法)从 到 的范围。loc
loc="upper right"
(0, 0)
(1, 1)
(x0, y0, width, height) = (0, 0, 1, 1)
若要将图例放置在轴边界框的外部,可以指定图例左下角的轴坐标元组。(x0, y0)
plt.legend(loc=(1.04, 0))
一种更通用的方法是使用 bbox_to_anchor
参数手动指定应放置图例的边界框。一个人可以限制自己只提供bbox的一部分。这将创建一个零范围框,从中,图例将沿参数给出的方向扩展。例如,(x0, y0)
loc
plt.legend(bbox_to_anchor=(1.04, 1), loc="upper left")
将图例放在轴外,使得图例的左上角位于轴坐标中的位置。(1.04, 1)
下面给出了更多的例子,其中还显示了不同参数之间的相互作用,如和。mode
ncols
l1 = plt.legend(bbox_to_anchor=(1.04, 1), borderaxespad=0)
l2 = plt.legend(bbox_to_anchor=(1.04, 0), loc="lower left", borderaxespad=0)
l3 = plt.legend(bbox_to_anchor=(1.04, 0.5), loc="center left", borderaxespad=0)
l4 = plt.legend(bbox_to_anchor=(0, 1.02, 1, 0.2), loc="lower left",
mode="expand", borderaxespad=0, ncol=3)
l5 = plt.legend(bbox_to_anchor=(1, 0), loc="lower right",
bbox_transform=fig.transFigure, ncol=3)
l6 = plt.legend(bbox_to_anchor=(0.4, 0.8), loc="upper right")
有关如何将 4 元组参数解释为 (如 中 所示)的详细信息,可以在此问题中找到。在由 4 元组给出的边界框内水平扩展图例。有关垂直展开的图例,请参阅此问题。bbox_to_anchor
l4
mode="expand"
有时,在图形坐标中指定边界框而不是轴坐标可能很有用。这在上面的示例中所示,其中参数用于将图例放在图的左下角。l5
bbox_transform
将图例放在轴外通常会导致不希望的情况,即它完全或部分在图形画布之外。
此问题的解决方案有:
调整子图参数
可以使用plt.subplots_adjust
来调整子图参数,使轴占用较少的图空间(从而为图例留出更多空间)。例如,
plt.subplots_adjust(right=0.7)
在图的右侧留出 30% 的空间,可以放置图例。
紧凑布局
使用plt.tight_layout
允许自动调整子图参数,使图中的元素紧贴图形边缘。不幸的是,在这种自动性中没有考虑图例,但是我们可以提供一个整个子图区域(包括标注)将适合的矩形框。
plt.tight_layout(rect=[0, 0, 0.75, 1])
保存带有bbox_inches = “tight”
的图形 plt.savefig
的参数可用于保存图形,以便画布上的所有艺术家(包括图例)都适合保存的区域。如果需要,数字大小会自动调整。bbox_inches = "tight"
plt.savefig("output.png", bbox_inches="tight")
自动调整子图参数
一种自动调整子图位置的方法,使图例适合画布内部而不更改图形大小,可以在以下答案中找到:创建具有精确大小且无填充的图形(以及轴外的图例)
上述案例之间的比较:
人物图例
可以使用图例而不是轴,matplotlib.figure.Figure.legend
。这对于不需要特殊参数的 Matplotlib 版本 2.1 或更高版本特别有用
fig.legend(loc=7)
为人物不同轴上的所有艺术家创造一个传奇。图例是使用参数放置的,类似于将其放置在轴内的方式,但参考整个图形 - 因此它将在某种程度上自动位于轴外。剩下的工作是调整子图,使图例和轴之间没有重叠。在这里,上面的“调整子图参数”点将很有帮助。例如:loc
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 2*np.pi)
colors = ["#7aa0c4", "#ca82e1", "#8bcd50", "#e18882"]
fig, axes = plt.subplots(ncols=2)
for i in range(4):
axes[i//2].plot(x, np.sin(x+i), color=colors[i], label="y=sin(x + {})".format(i))
fig.legend(loc=7)
fig.tight_layout()
fig.subplots_adjust(right=0.75)
plt.show()
专用子图轴内的图例
使用的替代方法是将图例放置在其专用的子图轴中 ()。由于图例子图应小于图,因此我们可以在轴创建时使用。我们可以隐藏轴,但我们仍然放了一个图例。图例句柄和标注需要通过从真实图中获取,然后可以提供给子图中的图例。下面是一个完整的示例。bbox_to_anchor
lax
gridspec_kw={"width_ratios":[4, 1]}
lax.axis("off")
h, l = ax.get_legend_handles_labels()
lax
lax.legend(h, l)
import matplotlib.pyplot as plt
plt.rcParams["figure.figsize"] = 6, 2
fig, (ax, lax) = plt.subplots(ncols=2, gridspec_kw={"width_ratios":[4, 1]})
ax.plot(x, y, label="y=sin(x)")
....
h, l = ax.get_legend_handles_labels()
lax.legend(h, l, borderaxespad=0)
lax.axis("off")
plt.tight_layout()
plt.show()
这会产生一个在视觉上与上面的情节非常相似的情节:
我们也可以使用第一个轴来放置图例,但使用图例轴,bbox_transform
ax.legend(bbox_to_anchor=(0, 0, 1, 1), bbox_transform=lax.transAxes)
lax.axis("off")
在此方法中,我们不需要从外部获取图例句柄,但需要指定参数。bbox_to_anchor
loc