Question: While reading a paper for my thesis I encountered this graph (b):  I've tried to recreate the second graph which is the one I would like to use for my results: import numpy as np import matplotlib.pyplot as plt from matplotlib.gridspec import GridSpec years = np.linspace(1300, 2000, 700) np.random.seed(42) delta_13C = np.cumsum(np.random.normal(0, 0.1, 700)) delta_13C = delta_13C - np.mean(delta_13C) delta_18O = np.cumsum(np.random.normal(0, 0.08, 700)) delta_18O = delta_18O - np.mean(delta_18O) temp_anomaly = np.cumsum(np.random.normal(0, 0.03, 700)) temp_anomaly = temp_anomaly - np.mean(temp_anomaly) temp_anomaly[-100:] += np.linspace(0, 1.5, 100) plt.style.use('default') plt.rcParams['font.size'] = 12 plt.rcParams['axes.linewidth'] = 1.5 plt.rcParams['axes.labelsize'] = 14 fig = plt.figure(figsize=(10, 8)) gs = GridSpec(3, 1, height_ratios=[1, 1, 1], hspace=0.2) ax1 = fig.add_subplot(gs[0]) ax1.plot(years, delta_13C, color='green', linewidth=1.0) ax1.set_ylabel('First', color='green', labelpad=10) ax1.tick_params(axis='y', colors='green') ax1.set_xlim(1300, 2000) ax1.set_ylim(-4, 4) ax1.xaxis.set_visible(False) ax1.spines['top'].set_visible(False) ax1.spines['bottom'].set_visible(False) ax1.spines['right'].set_visible(False) ax1.spines['left'].set_color('green') ax2 = fig.add_subplot(gs[1]) ax2.plot(years, delta_18O, color='blue', linewidth=1.0) ax2.yaxis.tick_right() ax2.yaxis.set_label_position("right") ax2.set_ylabel('Second', color='blue', labelpad=10) ax2.tick_params(axis='y', colors='blue') ax2.set_xlim(1300, 2000) ax2.set_ylim(-3, 3) ax2.xaxis.set_visible(False) ax2.spines['top'].set_visible(False) ax2.spines['bottom'].set_visible(False) ax2.spines['left'].set_visible(False) ax2.spines['right'].set_color('blue') ax3 = fig.add_subplot(gs[2]) ax3.plot(years, temp_anomaly, color='gray', linewidth=1.0) ax3.set_ylabel('Third', color='black', labelpad=10) ax3.set_xlim(1300, 2000) ax3.set_ylim(-1.0, 1.5) ax3.set_xlabel('Year (CE)') ax3.spines['top'].set_visible(False) ax3.spines['right'].set_visible(False) plt.show()  But the result is a bit different:  How can I bring the subplots closer together without blocking each other? As you can see in the graphic in the reference paper, the lines of the subplots almost touch each other.

Answer: The main change you'll need to make is to make the background color of your Axes transparent and to use a negative hspace to force the graphs to overlap a bit more: plt.rcParams['axes.facecolor'] = 'none' # transparent Axes background gs = GridSpec(3, 1, height_ratios=[1, 1, 1], hspace=-.1) # negative hspace for overlap  Adjusting the y-axis on your second chart will also be necessary here since they currently clip out just a touch of data. ax2.set_ylim(-3.5, 3.5)  Putting it all back into your script: import numpy as np import matplotlib.pyplot as plt from matplotlib.gridspec import GridSpec years = np.linspace(1300, 2000, 700) np.random.seed(42) delta_13C = np.cumsum(np.random.normal(0, 0.1, 700)) delta_13C = delta_13C - np.mean(delta_13C) delta_18O = np.cumsum(np.random.normal(0, 0.08, 700)) delta_18O = delta_18O - np.mean(delta_18O) temp_anomaly = np.cumsum(np.random.normal(0, 0.03, 700)) temp_anomaly = temp_anomaly - np.mean(temp_anomaly) temp_anomaly[-100:] += np.linspace(0, 1.5, 100) plt.style.use('default') plt.rcParams['font.size'] = 12 plt.rcParams['axes.linewidth'] = 1.5 plt.rcParams['axes.labelsize'] = 14 plt.rcParams['axes.facecolor'] = 'none' # make facecolor transparent fig = plt.figure(figsize=(10, 8)) gs = GridSpec(3, 1, height_ratios=[1, 1, 1], hspace=-.1) # negative hspace for overlap ax1 = fig.add_subplot(gs[0]) ax1.plot(years, delta_13C, color='green', linewidth=1.0) ax1.set_ylabel('First', color='green', labelpad=10) ax1.tick_params(axis='y', colors='green') ax1.set_xlim(1300, 2000) ax1.set_ylim(-4, 4) ax1.xaxis.set_visible(False) ax1.spines['top'].set_visible(False) ax1.spines['bottom'].set_visible(False) ax1.spines['right'].set_visible(False) ax1.spines['left'].set_color('green') ax2 = fig.add_subplot(gs[1]) ax2.plot(years, delta_18O, color='blue', linewidth=1.0) ax2.yaxis.tick_right() ax2.yaxis.set_label_position("right") ax2.set_ylabel('Second', color='blue', labelpad=10) ax2.tick_params(axis='y', colors='blue') ax2.set_xlim(1300, 2000) ax2.set_ylim(-3.5, 3.5) # changed the y-limits ever slightly since the previous clipped data ax2.xaxis.set_visible(False) ax2.spines['top'].set_visible(False) ax2.spines['bottom'].set_visible(False) ax2.spines['left'].set_visible(False) ax2.spines['right'].set_color('blue') ax3 = fig.add_subplot(gs[2]) ax3.plot(years, temp_anomaly, color='gray', linewidth=1.0) ax3.set_ylabel('Third', color='black', labelpad=10) ax3.set_xlim(1300, 2000) ax3.set_ylim(-1.0, 1.5) ax3.set_xlabel('Year (CE)') ax3.spines['top'].set_visible(False) ax3.spines['right'].set_visible(False) plt.show()   Of course a touch of structure can clean up the script a bit as well: from collections import namedtuple import numpy as np import matplotlib.pyplot as plt from matplotlib.gridspec import GridSpec years = np.linspace(1300, 2000, 700) np.random.seed(42) delta_13C = np.cumsum(np.random.normal(0, 0.1, 700)) delta_13C = delta_13C - np.mean(delta_13C) delta_18O = np.cumsum(np.random.normal(0, 0.08, 700)) delta_18O = delta_18O - np.mean(delta_18O) temp_anomaly = np.cumsum(np.random.normal(0, 0.03, 700)) temp_anomaly = temp_anomaly - np.mean(temp_anomaly) temp_anomaly[-100:] += np.linspace(0, 1.5, 100) plt.style.use('default') plt.rc('font', size=12) plt.rc('axes', linewidth=1.5, labelsize=14, facecolor='none') PlotSettings = namedtuple('PlotSettings', ['data', 'linecolor', 'labelcolor', 'ylabel', 'yrange']) configurations = [ PlotSettings(delta_13C, linecolor='green', labelcolor='green', ylabel='First', yrange=(-4 , 4 )), PlotSettings(delta_18O, linecolor='blue', labelcolor='blue', ylabel='Second', yrange=(-3.5, 3.5)), PlotSettings(temp_anomaly, linecolor='gray', labelcolor='black', ylabel='Third', yrange=(-1 , 1.5)), ] fig, axes = plt.subplots( nrows=len(configurations), ncols=1, figsize=(10, 8), sharex=True, sharey=False, gridspec_kw={'hspace': -.1}, ) for i, (config, ax) in enumerate(zip(configurations, axes.flat)): ax.plot(years, config.data, color=config.linecolor, linewidth=1.0) # Format the X/Y Axes ax.set_ylabel(config.ylabel, color=config.labelcolor, labelpad=10) ax.tick_params(axis='y', colors=config.labelcolor) ax.set_ylim(*config.yrange) ax.xaxis.set_visible(False) # Format the spines ax.spines[['top', 'bottom']].set_visible(False) if (i % 2) == 0: ax.spines['right'].set_visible(False) ax.spines['left' ].set_visible(True) ax.spines['left' ].set_color(config.labelcolor) else: ax.spines['right'].set_visible(True) ax.spines['left' ].set_visible(False) ax.spines['right'].set_color(config.labelcolor) ax.yaxis.tick_right() ax.yaxis.set_label_position("right") # Make special adjustments to the bottom-most plot axes.flat[-1].spines['bottom'].set_visible(True) axes.flat[-1].xaxis.set_visible(True) axes.flat[-1].set_xlabel('Year (CE)') axes.flat[-1].set_xlim(1300, 2000) plt.show()