python - Control Matplotlib legend box width for wrapping -
i trying fix width of legend box in matplotlib (python 2.7). here simple example of code using:
import numpy np import pylab plt fig = plt.figure(figsize=(8.5, 8.5)) ax = fig.add_axes([0.0882, 0.0588, 0.8882, 0.9118]) x = np.array([0,1,2,33]) y = np.array([0.1,2,4,8]) z = np.array([0,1,3.7,7]) t = np.array([0.5,1,12,41]) v = np.array([0.9,7,24,54]) = np.array([0.2,11,17,61]) q = np.array([0.4,17,15,80]) r = np.array([0.9,3.7,18,44]) s = np.array([0.2,10,19,31]) y1 = y+1 z1 = z+1 t1 = t+1 v1 = v+1 a1 = a+1 q1 = q+1 r1 = r+1 s1 = s+1 ax.plot(x,y,label='y') ax.plot(x,z,label='z') ax.plot(x,t,label='t') ax.plot(x,v,label='v') ax.plot(x,a,label='a') ax.plot(x,y1,label='y1') ax.plot(x,z1,label='z1') ax.plot(x,t1,label='t1') ax.plot(x,v1,label='v1') ax.plot(x,a1,label='a1') ax.plot(x,q1,label='q1') ax.plot(x,r1,label='r1') ax.plot(x,s1,label='s1') lg = ax.legend(loc='upper center', bbox_to_anchor=(0.5, -0.05), ncol=10) fig.savefig('a_test_position.png', facecolor='white', dpi = 300, bbox_inches='tight')
when keep first 3 ax.plot()
statements, . however, when include ax.plot()
statements, output becomes
problem: need legend box to:
- start @ 0 on x-axis
- end @ maximum x-value on x-axis (in case, max value 35)
- wrap new row after reaches maximum on x-axis
when there small number of entries (eg. first plot), want legend centered. code working correctly this, not need change behavior. however, need change behavior when there many entries legend needs wrap around new row (2nd plot).
how can done in matplotlib? there way specify size of legend box?
a solution iterate on ncol
argument until width of legend becomes larger width of axe. then, make legend expand entire width of axe using optimal value found ncol
, mode='expand'
option. in case entries can fit in single row, "centered layout" kept, without expanding legend width of axe.
below code sample shows how can done:
ncol = 1 lgwidth_old = 0. renderer = fig.canvas.get_renderer() while true: lg = ax.legend(loc='upper center', bbox_to_anchor=(0., -0.05, 1., 0.), borderaxespad=0, ncol=ncol) fig.canvas.draw() lgbbox = lg.get_window_extent(renderer).inverse_transformed(ax.transaxes) if lgwidth_old == lgbbox.width: # entries fit within single row. keep legend # , break loop. break if lgbbox.width < 1: # width of legend still smaller of axe. # continue iterating. ncol += 1 lgwidth_old = lgbbox.width else: # width of legend larger of axe. # backtrack ncol, plot legend span entire width of # axe, , break loop. ncol -= 1 lg = ax.legend(loc='upper center', bbox_to_anchor=(0., -0.05, 1., 0.), borderaxespad=0, ncol=ncol, mode='expand') break if ncol > 100: print('number max of iteration reached. wrong.') break
which results in (when added code):
Comments
Post a Comment