我正在开发一个程序,允许用户将不同数量的绘图放在轴上。我需要展示传说,并且情节标签很长,所以我认为最好在情节下显示。当我之前完成这项工作时,我总是只是缩小了一点情节,并将传说置于情节之下。既然有不同数量的情节,这并不是那么简单,因为我找不到一个很好的公式来确定缩小绘图的数量以及放下传说的距离,以免它被切断或重叠轴。
我已经编写了一个示例代码来演示我目前正在做的事情,这很丑陋。我目前正在检查绘图中有多少项,并尝试手动优化轴缩小和图例偏移参数,然后执行大if
循环以使用手动优化的值。它们没有针对此示例代码进行优化,但我认为它演示了我正在做的事情。
import matplotlib.pyplot as plt
import numpy as np
def find_scales(legendData):
leg_len = len(legendData)
if leg_len == 0:
height_scale = 1
legend_offset = 0
elif leg_len == 1:
height_scale = 0.96
legend_offset = -0.18
elif leg_len == 2:
height_scale = 0.95
legend_offset = -0.25
elif leg_len == 3:
height_scale = 0.94
legend_offset = -0.35
elif leg_len == 4:
height_scale = 0.93
legend_offset = -0.45
elif leg_len == 5:
height_scale = 0.93
legend_offset = -0.57
elif leg_len == 6:
height_scale = 0.93
legend_offset = -0.68
elif leg_len == 7:
height_scale = 0.93
legend_offset = -0.82
elif leg_len == 8:
height_scale = 0.93
legend_offset = -0.98
elif leg_len == 9:
height_scale = 0.92
legend_offset = -1.3
elif leg_len == 10:
height_scale = 0.92
legend_offset = -1.53
else:
height_scale = 0.92
legend_offset = -1.8
return height_scale, legend_offset
num_plots = 3
x_range = np.arange(10)
fig,ax = plt.subplots()
for i in range(num_plots):
ax.plot(x_range, np.random.rand(10))
legend_labels = ['a','b','c','d','e','f','g','h','i','j'][:num_plots]
box = ax.get_position()
height_scale, legend_offset = find_scales(legend_labels)
ax.set_position([box.x0, box.y0 + box.height * (1-height_scale), #left, bottom, width, height
box.width, box.height * height_scale])
ax.legend(legend_labels, loc=3, bbox_to_anchor=(0,legend_offset), borderaxespad=0.)
plt.show()
我希望有更好的方法来做到这一点。我希望图例在轴下。我不能让图例与轴或x标签重叠。我不能因为太低而超出图形而被切断。有没有办法这样做,所以轴和图例会自动调整大小以适应图形?
答案 0 :(得分:1)
在此问题的答案中显示了一种纠正轴位置的方法,以便图例有足够的空间:Creating figure with exact size and no padding (and legend outside the axes)
对于位于底部的图例,解决方案要简单得多。基本上,您只需要从轴高度减去图例高度,然后将图例高度向顶部移动轴。
import matplotlib.pyplot as plt
fig = plt.figure(figsize = [3.5,2])
ax = fig.add_subplot(111)
ax.set_title('title')
ax.set_ylabel('y label')
ax.set_xlabel('x label')
ax.plot([1,2,3], marker="o", label="quantity 1")
ax.plot([2,1.7,1.2], marker="s", label="quantity 2")
def legend(ax, x0=0.5,y0=0, pad=0.5,**kwargs):
otrans = ax.figure.transFigure
t = ax.legend(bbox_to_anchor=(x0,y0), loc=8, bbox_transform=otrans,**kwargs)
ax.figure.tight_layout(pad=pad)
ax.figure.canvas.draw()
tbox = t.get_window_extent().transformed( ax.figure.transFigure.inverted() )
bbox = ax.get_position()
ax.set_position([bbox.x0, bbox.y0+tbox.height,bbox.width, bbox.height-tbox.height])
legend(ax,y0=0, borderaxespad=0.2)
plt.savefig(__file__+'.pdf')
plt.show()