Here is a slightly revised version of your script.
It has a separate axes for labeling whose width is determined by the
maximum width of the labels (using MaxExtent from axes_grid toolkit).
Give it a try and see if it fits your needs.
Regards,
-JJ
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import gamma
from mpl_toolkits.axes_grid import make_axes_locatable
fig = plt.figure(1, (10, 10))
ax1 = fig.add_subplot(1, 1, 1)
labels = ('0-9', '10-19', '20-29', '30-39', '40-49',
'50-59', '60-69', '70-79', '80-89', '90-99')
pad = np.max([len(i) for i in labels]) * .15
divider = make_axes_locatable(ax1)
from mpl_toolkits.axes_grid.axes_size import MaxExtent
labeltexts = []
labelextent = MaxExtent(labeltexts, "width")
padsmall=0.1
label_axes = divider.new_horizontal(size=labelextent, pad=padsmall,
sharey=ax1, frame_on=False)
label_axes.xaxis.set_visible(False)
label_axes.yaxis.set_visible(False)
fig.add_axes(label_axes)
ax2 = divider.new_horizontal(size="100%", pad=padsmall, sharey=ax1)
fig.add_axes(ax2)
N = 10
ind = np.arange(N) # the x locations for the groups
width = 0.35 # the width of the bars
x = [gamma.pdf(i, 1, scale=2) for i in range(N)]
y = [gamma.pdf(i, 5, scale=1) for i in range(N)]
ind = np.arange(N)
ax1.barh(ind, x, align="center")
ax2.barh(ind, y, align="center")
for loc, spine in ax1.spines.iteritems():
if loc in ['left','top']:
spine.set_color('none') # don't draw spine
for loc, spine in ax2.spines.iteritems():
if loc in ['right','top']:
spine.set_color('none') # don't draw spine
ax1.set_title('Men')
ax2.set_title('Women')
ax1.set_ylim(-0.5, N-0.5)
#ax2.set_ylim(0, N)
# Name bars
ax1.set_yticks(ind)
ax1.xaxis.set_ticks_position('bottom')
ax2.xaxis.set_ticks_position('bottom')
ax1.yaxis.set_ticks_position('right')
ax2.yaxis.set_ticks_position('left')
for tl in ax1.get_yticklabels()+ax2.get_yticklabels():
tl.set_visible(False)
for i, l in zip(ind, labels):
l = label_axes.annotate("$%s$"%l, (0.5, i), ha="center", va="center")
labeltexts.append(l)
ax1.set_xlim(0.5, 0)
ax2.set_xlim(0, 0.5)
plt.show()
On Sun, Jan 31, 2010 at 7:40 PM, Renato Alves <[email protected]> wrote:
> Hi everyone
>
> I've been going around matplotlib objects trying to find a way to
> pre-calculate positions depending on input.
>
> I'm trying to create a function that draws two barplots facing opposite
> directions.
>
> This is what I managed so far:
>
> ###
>
> import numpy as np
> import matplotlib.pyplot as plt
> from scipy.stats import gamma
> from mpl_toolkits.axes_grid import make_axes_locatable
>
> fig = plt.figure(1, (10, 10))
> ax1 = fig.add_subplot(1, 1, 1)
>
> ax1.set_xlim(1,0)
>
> labels = ('0-9', '10-19', '20-29', '30-39', '40-49',
> '50-59', '60-69', '70-79', '80-89', '90-99')
>
> pad = np.max([len(i) for i in labels]) * .15
>
> divider = make_axes_locatable(ax1)
> ax2 = divider.new_horizontal(size="100%", pad=pad, sharey=ax1)
> fig.add_axes(ax2)
>
> N = 10
> ind = np.arange(N) # the x locations for the groups
> width = 0.35 # the width of the bars
>
> x = [gamma.pdf(i, 1, scale=2) for i in range(N)]
> y = [gamma.pdf(i, 5, scale=1) for i in range(N)]
>
> ind = np.arange(N)
>
> ax1.barh(ind, x)
> ax2.barh(ind, y)
>
> for loc, spine in ax1.spines.iteritems():
> if loc in ['left','top']:
> spine.set_color('none') # don't draw spine
>
> for loc, spine in ax2.spines.iteritems():
> if loc in ['right','top']:
> spine.set_color('none') # don't draw spine
>
> ax1.set_title('Men')
> ax2.set_title('Women')
>
> ax1.set_ylim(0, N)
> ax2.set_ylim(0, N)
>
> # Name bars
> ax1.set_yticks(ind + width)
> ax1.xaxis.set_ticks_position('bottom')
> ax2.xaxis.set_ticks_position('bottom')
> ax1.yaxis.set_ticks_position('right')
> ax2.yaxis.set_ticks_position('left')
>
> for tl in ax1.get_yticklabels():
> tl.set_visible(False)
>
> ax2.set_yticklabels(labels,
> horizontalalignment='center'
> )
>
> for i in ax2.get_yticklabels():
> i.set_position((-(pad * .12) , 0))
>
> plt.show()
>
> ###
>
> However I would like to generalize this function but he space between
> the two plots and the position of the labels is giving me a hard time.
>
> In particular, the lines:
>
> pad = np.max([len(i) for i in labels]) * .15
> i.set_position((-(pad * .12) , 0))
>
> include two values (.15 and .12) that are completely arbitrary and
> defined by trial and error for current labels.
>
> However with different labels:
> labels = ('0000-9000', '10-19', '20-29', '30-39', '40-49',
> '50-59', '60-69', '70-79', '80-89', '90000-99000')
>
> the values are no longer valid and the final image is no longer properly
> aligned.
>
> I know my current approach is not the proper way but due to the
> complexity of matplotlib, my very superficial knowledge about it and the
> overwhelming documentation this was the closest I could get.
>
> In the end I would like to contribute the final result as something to
> be included in the gallery/examples section of the website as I'm
> positive that it will be helpful to others.
>
> Any comment or suggestion is extremely welcome.
>
> Cheers,
> Renato
>
> ------------------------------------------------------------------------------
> The Planet: dedicated and managed hosting, cloud storage, colocation
> Stay online with enterprise data centers and the best network in the business
> Choose flexible plans and management services without long-term contracts
> Personal 24x7 support from experience hosting pros just a phone call away.
> http://p.sf.net/sfu/theplanet-com
> _______________________________________________
> Matplotlib-users mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/matplotlib-users
>
------------------------------------------------------------------------------
The Planet: dedicated and managed hosting, cloud storage, colocation
Stay online with enterprise data centers and the best network in the business
Choose flexible plans and management services without long-term contracts
Personal 24x7 support from experience hosting pros just a phone call away.
http://p.sf.net/sfu/theplanet-com
_______________________________________________
Matplotlib-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-users