1

I am trying to plot two subplots. One of them is a heatmap from seaborn library and other one is line plot from matplotlib. Line plot is showing gasoline prices through the 2022 and heatmap shows the metro line passengers through the months of the 2022. What I am trying to do is showing the relation between gasoline prices and metro passenger counts. Here are my codes:

import matplotlib.pyplot as plt
import seaborn as sns
ddf = pd.DataFrame(total_passengers_by_lines, columns = months, index=lines)
fig, (ax1, ax2) = plt.subplots(2, figsize = (25,10), gridspec_kw={'height_ratios': [1, 3]})
fig.suptitle('The Unleaded Gasoline 95 Prices and Total Passengers Per Lines Through The Year 2022',fontsize=15)
ax1.plot(eu_gas.index, eu_gas['Unleaded Gasoline 95'])
ax1.axes.get_xaxis().set_ticks([])
ax2 = sns.heatmap(ddf, linewidth=1, cmap='Blues', annot= True, robust = True, fmt='d')

The dataframe is something like this:

Jannuary    February    March   April   May     June    July    August  September   October     November    December
272674     296034     449074    738360  1029714 937376  995368  1072082 1069054     1225378     588223     457463

Index is the metro line name (for ex.): F1-TAKSIM-KABATAS FUNICULAR LINE

Here is the result: enter image description here

What I want is to make line plot starts at the same vertical line in heatmap and ends where heatmap ends. So that's how relation can be more clear. But no matter what I tried I couldn't make line plot less wider. I tried to add 'width_ratios':[2, 1] to the gridspec_kw parameter like this:

fig, (ax1, ax2) = plt.subplots(2, figsize = (25,10), gridspec_kw={'height_ratios': [1, 3], 'width_ratios':[2, 1]})

But this method gives me an error:

ValueError: Expected the given number of width ratios to match the number of columns of the grid

Perhaps I need to change the first parameter of the subplots, but how so? There are only 2 plots and 1 column.

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
milikest
  • 61
  • 1
  • 9
  • The first positional argument in `plt.subplots` is `nrow`, which you have set to 2. You have not set `ncols`, as such there is only 1 column of subplots, and you may not use `'width_ratios':[2, 1]`, as the error states. – Trenton McKinney Jun 10 '23 at 17:15
  • Defining ncols=1, nrows=2 doesn't work. It throws same error. – milikest Jun 10 '23 at 17:48
  • That's because you still only have 1 column. **Expected the given number of width ratios to match the number of columns** – Trenton McKinney Jun 10 '23 at 17:49

1 Answers1

3

The reason for the different widths is because the heatmap has the colorbar. One way to do this is by using gridspec. Create a 2x2 gridspec instead of a 2x1 subplot, and then arrange them as needed. I have used some dummy data and created it. You can adjust the width_ratios to what you need.

import matplotlib.gridspec
## Create 2x2 gridspec and adjust width_ratio
gs = matplotlib.gridspec.GridSpec(2,2, width_ratios=[100,1], height_ratios=[1,3])

fig = plt.figure(figsize = (25,10))
ax1 = fig.add_subplot(gs[0,0])  ## As you want to reduce top graph, use position 0,0
ax2 = fig.add_subplot(gs[1,0])  ## Use second row for heatmap
ax3 = fig.add_subplot(gs[1,0])  ## Use for colorbar

#fig, (ax1, ax2) = plt.subplots(2, figsize = (25,10), gridspec_kw={'height_ratios': [1, 3]})
fig.suptitle('The Unleaded Gasoline 95 Prices and Total Passengers Per Lines Through The Year 2022',fontsize=15)
ax1.plot(eu_gas.index, eu_gas['Unleaded Gasoline 95'])
ax1.axes.get_xaxis().set_ticks([])
sns.heatmap(ddf, linewidth=1, cmap='Blues', annot= True, robust = True, fmt='d', ax=ax2, cbar_ax=ax3)

enter image description here

Redox
  • 9,321
  • 5
  • 9
  • 26
  • Note that `ax2 = sns.heatmap(ddf, ...)` plots on the "current ax", and assigns that `ax` to the variable `ax2`. By coincidence, the "current ax" being the last created subplot, you don't see the problem in this example. The correct call would be `sns.heatmap(ddf, ..., ax=ax2)`. Even better would be to also explicitly create the `ax` for the colorbar, and give that as `cbar_ax` parameter. I.e. `ax2 = fig.add_subplot(gs[1,0]; ax3 = fig.add_subplot(gs[1,1]; sns.heatmap(..., cbar_ax=ax3, ax=ax2)`, – JohanC Jun 10 '23 at 20:16