1

I got a little problem and google couldn't really help me out. Here's my code:

from matplotlib import pyplot as plt
import numpy as np

job_r = list(ct_t.JobRole.unique())
att_y = ct_t[ct_t['Attrition']=='Yes']['Percentage'].values
att_n = ct_t[ct_t['Attrition']=='No']['Percentage'].values

# Sort by number of sales staff
idx = att_n.argsort()
job_r, att_y, att_n = [np.take(x, idx) for x in [job_r, att_y, att_n]]
y = np.arange(att_y.size)

fig, axes = plt.subplots(ncols=2, sharey=True, figsize=[8,8])
axes[0].barh(y, att_n, align='center', color='#43e653', zorder=10)
axes[0].set(title='NO')

axes[1].barh(y, att_y, align='center', color='#ed1c3c', zorder=10)
axes[1].set(title='YES')

axes[0].invert_xaxis()
axes[0].set(yticks=y, yticklabels=job_r)
axes[0].yaxis.tick_right()

for ax in axes.flat:
    ax.margins(0.03)
    ax.grid(True)

fig.tight_layout()
fig.subplots_adjust(wspace=0.7)
plt.show()

My current output:

enter image description here

  1. Is there any way to center the shared y labels in the middle between those two subplots?

  2. Can I increase the x-axis up to 1.0 ? Each time I do something like: axes[1].set_xlabels(1.0) my whole plot turns upside down.

JohanC
  • 71,591
  • 8
  • 33
  • 66
soulwreckedyouth
  • 465
  • 1
  • 3
  • 12
  • 1
    Hi it would be easier to help you if we had some sample data. Check also [how to provide a minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) – Björn Apr 06 '20 at 21:26

1 Answers1

3

Here is a way to achieve the desired plot.

Extending the x limits to 1 is easier if done before inverting the x-axis. The code to center and reposition the labels come from this post.

import matplotlib.pyplot as plt
import matplotlib.transforms
import numpy as np

# first create some test data compatible with the question's data
job_r = ["".join(np.repeat(letter, np.random.randint(4, 15))) for letter in 'ABCDEFG']
att_y = np.random.uniform(0.5, 0.9, len(job_r))
att_n = 1 - att_y

# Sort by number of sales staff
idx = att_n.argsort()
job_r, att_y, att_n = [np.take(x, idx) for x in [job_r, att_y, att_n]]
y = np.arange(att_y.size)

fig, axes = plt.subplots(ncols=2, sharey=True, figsize=[8, 8])
axes[0].barh(y, att_n, align='center', color='#43e653', zorder=10)
axes[0].set(title='NO')

axes[1].barh(y, att_y, align='center', color='#ed1c3c', zorder=10)
axes[1].set(title='YES')
axes[1].set_xlim(xmax=1)

axes[0].set(yticks=y, yticklabels=job_r)
axes[0].yaxis.tick_right()
axes[0].set_xlim(xmax=1)
axes[0].invert_xaxis()

for ax in axes:
    ax.margins(0.03)
    ax.grid(True)

fig.tight_layout()
fig.subplots_adjust(wspace=0.7)

plt.setp(axes[0].yaxis.get_majorticklabels(), ha='center')

# Create offset transform by some points in x direction
dx = 60 / 72.
dy = 0 / 72.
offset = matplotlib.transforms.ScaledTranslation(dx, dy, fig.dpi_scale_trans)
# apply offset transform to all y ticklabels.
for label in axes[0].yaxis.get_majorticklabels():
    label.set_transform(label.get_transform() + offset)

plt.show()

resulting plot

JohanC
  • 71,591
  • 8
  • 33
  • 66