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