Solution with pandas
When using the pandas plotting function, you can remove the x-axis label by setting xlabel=''
. You can additionally remove the x-axis tick marks and tick labels by using the following method after creating your first plot for example: axes[0].xaxis.set_visible(False)
.
You can adjust the vertical space between the subplots by adding gridspec_kw=dict(hspace=0.3)
to the plt.subplots
function call. Finally, you can also adjust the space between the title and the subplot by using the following method after creating your first plot for example: axes[0].set_title('ROE', pad=5)
.
To illustrate this, let me first create a reproducible sample dataset similar to yours:
import numpy as np # v 1.19.2
import pandas as pd # v 1.1.3
import matplotlib.pyplot as plt # v 3.3.2
# Create sample dataset stored as a pandas dataframe
rng = np.random.default_rng(seed=1) # random number generator
years = np.arange(2013, 2020)
symbols = np.array(list('ABCD'))
df = pd.DataFrame(10+rng.integers(-5, 6, size=(symbols.size*years.size, 3)),
columns=['roe', 'roa', 'eps'])
df['symbol'] = np.repeat(symbols, years.size)
df['date'] = symbols.size*list(years)
df.head()
# roe roa eps symbol date
# 0 10 10 13 A 2013
# 1 15 5 6 A 2014
# 2 14 15 7 A 2015
# 3 8 14 9 A 2016
# 4 8 14 7 A 2017
I suggest using a for loop to plot the variables you want from the dataframe when plotting several variables at once. This lets you format all the subplots in one go. In the following example, I remove the x-axis and the legend from all three subplots then add them back only where I want them:
# Create figure with space between subplots: note that sharex=True is not needed
fig, axs = plt.subplots(3, 1, gridspec_kw=dict(hspace=0.3), figsize=(9, 7))
# Loop through axes to plot bar charts with titles but no x labels, x ticks or legends
for ax, var in zip(axs.flat, ['roe', 'roa', 'eps']):
df.pivot('date','symbol').plot.bar(y=var, ax=ax, xlabel='', rot=0)
ax.set_title(var.upper(), pad=5)
ax.xaxis.set_visible(False) # remove this and add sharex=True for tick marks only
ax.legend().remove()
# Add x-axis ticks and tick labels to last subplot and add legend
axs[-1].xaxis.set_visible(True)
axs[1].legend(loc=(1.05, 0.25), frameon=False);

Solution with seaborn
The seaborn package is designed to produce this type of figure in a convenient way which is why it is worth adding an example using seaborn, created with the same data as the one above and this time keeping the default tick marks. The dataframe must first be reshaped to have the three variables to be plotted contained in a single column. Note that the only downside with seaborn is that you cannot easily change the width of the bars. You can refer to the documentation linked below for more details and examples.
import seaborn as sns # v 0.11.0
df_sns = df.melt(id_vars=['date', 'symbol'])
df_sns.head()
# date symbol variable value
# 0 2013 A roe 10
# 1 2014 A roe 15
# 2 2015 A roe 14
# 3 2016 A roe 8
# 4 2017 A roe 8
g = sns.catplot(kind='bar', data=df_sns, x='date', y='value', hue='symbol',
row='variable', height=2, aspect=3.5, saturation=1)
g.fig.subplots_adjust(hspace=0.3)
g.set_axis_labels(x_var='', y_var='')
for ax, var in zip(g.axes.flat, g.row_names):
ax.set_title(var.upper(), pad=5)

Seaborn documentation: catplot, barplot, tutorial on multi-plot grids