I have generated this bar-chart
Using this code:
s = """level,margins_fluid,margins_vp
Volume,0,0
1L*,0.718,0.690
2L,0.501,0.808
5L,0.181,0.920
MAP,0,0
64*,0.434,0.647
58,0.477,0.854
52,0.489,0.904
Exam,0,0
dry,0.668,0.713
euvolemic*,0.475,0.798
wet,0.262,0.893
History,0,0
COPD*,0.506,0.804
Kidney,0.441,0.778
HF,0.450,0.832
Case,0,0
1 (PIV),0.435,0.802
2 (CVC)*,0.497,0.809"""
data = np.array([a.split(',') for a in s.split("\n")])
fluid_vp_1_2 = pd.DataFrame(data[1:], columns=data[0])
fluid_vp_1_2['margins_fluid'] = fluid_vp_1_2['margins_fluid'].apply(float)
fluid_vp_1_2['margins_vp'] = fluid_vp_1_2['margins_vp'].apply(float)
fluid_vp_1_2
variableNames = {'Volume', 'MAP', 'Exam', 'History', 'Case'}
font_color = '#525252'
hfont = {'fontname':'DejaVu Sans'}
facecolor = '#eaeaf2'
index = fluid_vp_1_2.index#['level']
column0 = fluid_vp_1_2['margins_fluid']*100
column1 = fluid_vp_1_2['margins_vp']*100
title0 = 'Fluids'
title1 = 'Vasopressors'
fig, axes = plt.subplots(figsize=(10,5), facecolor=facecolor, ncols=2, sharey=True)
axes[0].barh(index, column0, align='center', color='dimgray', zorder=10)
axes[0].set_title(title0, fontsize=18, pad=15, color='black', **hfont)
axes[1].barh(index, column1, align='center', color='silver', zorder=10)
axes[1].set_title(title1, fontsize=18, pad=15, color='black', **hfont)
# If you have positive numbers and want to invert the x-axis of the left plot
axes[0].invert_xaxis()
# To show data from highest to lowest
plt.gca().invert_yaxis()
axes[0].set(xlim = [100,0])
axes[1].set(xlim = [0,100])
axes[0].yaxis.tick_right()
axes[0].set_yticks(range(len(fluid_vp_1_2)))
maxWordLength = fluid_vp_1_2['level'].apply(lambda x: len(x)).max()
formattedyticklabels = [r'$\bf{'+f"{t}"+r'}$'
if t in variableNames else t for t in fluid_vp_1_2['level']]
axes[0].set_yticklabels(formattedyticklabels, ha='center', position=(1.12, 0))
axes[0].tick_params(right = False)
axes[1].tick_params(left = False)
fig.tight_layout()
plt.savefig("fluid_vp_1_2.jpg")
plt.show()
However, I would like to modify this chart to more closely resemble the below example, where the y-axis labels are on the left-hand side, bi-directional bars are making contact in the center, white background, more vertical in shape (shrunken x-axis), add x-axis label (“adjusted proportion of respondents”), but I would still like to maintain the order of variables and the gaps in bars caused by the bolded header labels like Volume
, MAP
, etc.
Any tips?
There is a some simplification/factorization you can deal with to make styling your plots easier. But you are basically almost there. Just set the tick labels and remove spaces between plots with fig.subplots_adjust(wspace=0)
(you have to remove fig.tight_layout()
):
from io import StringIO
import matplotlib.pyplot as plt
import pandas as pd
s = """level,margins_fluid,margins_vp
Volume,0,0
1L*,0.718,0.690
2L,0.501,0.808
5L,0.181,0.920
MAP,0,0
64*,0.434,0.647
58,0.477,0.854
52,0.489,0.904
Exam,0,0
dry,0.668,0.713
euvolemic*,0.475,0.798
wet,0.262,0.893
History,0,0
COPD*,0.506,0.804
Kidney,0.441,0.778
HF,0.450,0.832
Case,0,0
1 (PIV),0.435,0.802
2 (CVC)*,0.497,0.809"""
# building df directly with pandas
fluid_vp_1_2 = pd.read_csv(StringIO(s))
fluid_vp_1_2['margins_fluid'] = fluid_vp_1_2['margins_fluid']*100
fluid_vp_1_2['margins_vp'] = fluid_vp_1_2['margins_vp']*100
# style parameters for all plots
title_format = dict(
fontsize=18,
pad=15,
color='black',
fontname='DejaVu Sans'
)
plot_params = dict(
align='center',
zorder=10,
legend=None,
width=0.9
)
grid_params = dict(
zorder=0,
axis='x'
)
tick_params = dict(
left=False,
which='both'
)
variableNames = {'Volume', 'MAP', 'Exam', 'History', 'Case'}
fig, axes = plt.subplots(figsize=(8,10), ncols=2, sharey=True, facecolor='#eaeaf2')
# removing spaces between plots
fig.subplots_adjust(wspace=0)
# plotting Fluids
fluid_vp_1_2.plot.barh(y='margins_fluid', ax=axes[0], color='dimgray', **plot_params)
axes[0].grid(**grid_params)
axes[0].set_title('Fluids', **title_format)
axes[0].tick_params(**tick_params)
# plotting Vasopressors
fluid_vp_1_2.plot.barh(y='margins_vp', ax=axes[1], color='silver', **plot_params)
axes[1].grid(**grid_params)
axes[1].set_title('Vasopressors', **title_format)
axes[1].tick_params(**tick_params)
# adjust axes
axes[0].invert_xaxis()
plt.gca().invert_yaxis()
axes[0].set(xlim = [100,0])
axes[1].set(xlim = [0,100])
# adding y labels
formattedyticklabels = [rf'$\bf{{{t}}}$'
if t in variableNames else t for t in fluid_vp_1_2['level']]
axes[0].set_yticklabels(formattedyticklabels)
plt.show()
Edit: you can get a "longer" plot by changing figsize
.
Output for figsize=(8,10)
: