[英]Matplotlib extend best positioning also outside the plot
我試圖繪制幾個數據,在某些情況下,占據整個情節。
版本2的默認選項應該是“最佳”,它會嘗試找到將圖例放置在圖中的最佳位置。 有沒有辦法擴展選項,以便在空間不足的情況下將圖例放在圖表之外?
否則,matplotlib是否有一個選項(不占用所有系列的最大值並添加手動填充)以自動添加ylim填充並為圖例提供空間並放置在繪圖內?
主要思想是避免手動調整繪圖,自動創建多個繪圖。
簡單的MWE如下:
%matplotlib inline
%config InlineBackend.figure_format = 'svg'
import scipy as sc
import matplotlib.pyplot as plt
plt.close('all')
x = sc.linspace(0, 1, 50)
y = sc.array([sc.ones(50)*0.5, x, x**2, (1-x), (1-x**2)]).T
fig = plt.figure('Fig')
ax = fig.add_subplot(111)
lines = ax.plot(x, y)
leg = ax.legend([lines[0], lines[1], lines[2], lines[3], lines[4]],
[r'$\mathrm{line} = 0.5$', r'$\mathrm{line} = x$', r'$\mathrm{line} = x^2$',
r'$\mathrm{line} = 1-x$',r'$\mathrm{line} = 1-x^2$'], ncol=2)
fig.tight_layout()
沒有自動方式將圖例放置在軸外的“最佳”位置。
您可能決定始終在軸內留出足夠的空間 ,以使圖例不會與任何東西重疊。 為此你可以使用ax.margins
。 例如
ax.margins(y=0.25)
將在y軸的兩端產生25%的余量,如果它有3列,則有足夠的空間來托管圖例。
然后,您可以決定始終使用相同的位置,例如loc="upper center"
,以獲得所有圖表中的一致結果。 這樣做的缺點在於它取決於圖形尺寸,並且它還在軸的另一端添加(可能不期望的)邊緣。 如果您可以使用該保證金,則自動確定所需保證金的方法如下:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.transforms
x = np.linspace(0, 1, 50)
y = np.array([np.ones(50)*0.5, x, x**2, (1-x), (1-x**2)]).T
fig = plt.figure('Fig')
ax = fig.add_subplot(111)
lines = ax.plot(x, y)
def legend_adjust(legend, ax=None ):
if ax == None: ax =plt.gca()
ax.figure.canvas.draw()
bbox = legend.get_window_extent().transformed(ax.transAxes.inverted() )
print bbox.height
ax.margins(y = 2.*bbox.height)
leg = plt.legend(handles=[lines[0], lines[1], lines[2], lines[3], lines[4]],
labels= [r'$\mathrm{line} = 0.5$', r'$\mathrm{line} = x$', r'$\mathrm{line} = x^2$',
r'$\mathrm{line} = 1-x$',r'$\mathrm{line} = 1-x^2$'], loc="upper center",
ncol=2)
legend_adjust(leg)
plt.show()
如果設置限制很好,您也可以自行調整限制:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.transforms
x = np.linspace(0, 1, 50)
y = np.array([np.ones(50)*0.5, x, x**2, (1-x), (1-x**2)]).T
fig = plt.figure('Fig')
ax = fig.add_subplot(111)
lines = ax.plot(x, y)
def legend_adjust(legend, ax=None, pad=0.05 ):
if ax == None: ax =plt.gca()
ax.figure.canvas.draw()
bbox = legend.get_window_extent().transformed(ax.transAxes.inverted() )
ymin, ymax = ax.get_ylim()
ax.set_ylim(ymin, ymax+(ymax-ymin)*(1.+pad-bbox.y0))
leg = plt.legend(handles=[lines[0], lines[1], lines[2], lines[3], lines[4]],
labels= [r'$\mathrm{line} = 0.5$', r'$\mathrm{line} = x$', r'$\mathrm{line} = x^2$',
r'$\mathrm{line} = 1-x$',r'$\mathrm{line} = 1-x^2$'], loc="upper center",
ncol=2)
legend_adjust(leg)
plt.show()
否則,您可能決定始終將圖例放在圖表之外 。 在這個答案中收集了一些技術。
特別感興趣的可能是將圖例放在圖形外部而不更改圖形,如本問題所述: 創建具有精確尺寸且沒有填充的圖形(以及軸外的圖例)
使其適應這種情況看起來像:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.transforms
x = np.linspace(0, 1, 50)
y = np.array([np.ones(50)*0.5, x, x**2, (1-x), (1-x**2)]).T
fig = plt.figure('Fig')
ax = fig.add_subplot(111)
lines = ax.plot(x, y)
def legend(ax=None, x0=1,y0=1, direction = "v", padpoints = 3,**kwargs):
if ax == None: ax =plt.gca()
otrans = ax.figure.transFigure
t = ax.legend(bbox_to_anchor=(x0,y0), loc=1, bbox_transform=otrans,**kwargs)
plt.tight_layout()
ax.figure.canvas.draw()
plt.tight_layout()
ppar = [0,-padpoints/72.] if direction == "v" else [-padpoints/72.,0]
trans2=matplotlib.transforms.ScaledTranslation(ppar[0],ppar[1],fig.dpi_scale_trans)+\
ax.figure.transFigure.inverted()
tbox = t.get_window_extent().transformed(trans2 )
bbox = ax.get_position()
if direction=="v":
ax.set_position([bbox.x0, bbox.y0,bbox.width, tbox.y0-bbox.y0])
else:
ax.set_position([bbox.x0, bbox.y0,tbox.x0-bbox.x0, bbox.height])
legend(handles=[lines[0], lines[1], lines[2], lines[3], lines[4]],
labels= [r'$\mathrm{line} = 0.5$', r'$\mathrm{line} = x$', r'$\mathrm{line} = x^2$',
r'$\mathrm{line} = 1-x$',r'$\mathrm{line} = 1-x^2$'],
y0=0.8, direction="h", borderaxespad=0.2)
plt.show()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.