1

I am trying to make a grid of subplots where one axis spans two grid locations. I can achieve this easily with plt.subplots, gridspec_kw, and plt.subplot2grid:

import matplotlib.pyplot as plt
fig, ax = plt.subplots(2,3,sharex=True, sharey=True, gridspec_kw={'width_ratios':[1,1,0.8]})
axi = plt.subplot2grid((2,3),(0,2),rowspan=2)
plt.show()

Basic setup

However, I want the spanning axes on the right to be narrower. When I change width_ratios to [1,1,0.5], I get this:

Gridspec error

What happened to the other axes? Based on this answer, I can achieve what I want using GridSpec directly rather than using the convenience wrappers:

import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec

fig = plt.figure()
gs = GridSpec(nrows=2, ncols=3, width_ratios=[1,1,0.5])
ax0 = plt.subplot(gs[0,0])
ax1 = plt.subplot(gs[0,1],sharey=ax0)
ax2 = plt.subplot(gs[1,0],sharex=ax0)
ax3 = plt.subplot(gs[1,1],sharex=ax1,sharey=ax2)
ax4 = plt.subplot(gs[:,2])
[plt.setp(z.get_yticklabels(),visible=False) for z in [ax1,ax3]]
[plt.setp(z.get_xticklabels(),visible=False) for z in [ax0,ax1]]
plt.show()

Using GridSpec

While this works, it is tedious to have to set everything manually, especially when I can get so close with just two lines of code. Does anybody have thoughts on how to make this work using subplots/subplot2grid or am I stuck doing it the long way? Is this worthy of an issue report on GitHub?

Community
  • 1
  • 1

2 Answers2

1

The issue to report is probably a different one than you imagine. I just created this one.

The equivalent of the working code with GridSpec (which is sure a valid and good solution), can be to use fig.add_subplot instead of plt.subplot2grid and remove the two unwanted axes from the initial grid.

import matplotlib.pyplot as plt
fig, ax = plt.subplots(2,3,sharex=True, sharey=True, gridspec_kw={'width_ratios':[1,1,0.8]})
axi = fig.add_subplot(133)

for a in ax[:,2]:
    a.axis("off")
plt.show()
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
  • This works, but a tweak is required. The problem is that `fig.add_subplot(133)` makes a regular grid based on the entire *figure* and hence ignores the gridspec width ratios. You'll see what I mean if you change `width_ratios` to `[1,1,2]` or `[1,1,0.3]`. In order for this method to work, for example with `width_ratios=[1,1,0.5]`, you'd have to calculate the values for the `subplot` call so everything lines up. In this case it would be `fig.add_subplot(155)` since `2*[1,1,0.5]=[2,2,1]` and `sum([2,2,1])=5`. I will accept this answer with this update! – Tiffany G. Wilson Jun 13 '18 at 17:51
  • Sure, feel free to update the answer, if you need to. – ImportanceOfBeingErnest Jun 13 '18 at 17:58
  • I just realized that the suggestion I made to your answer actually applies to my original question, so I will just make a new answer. Thanks for your help! – Tiffany G. Wilson Jun 13 '18 at 18:00
1

Thanks to the answer of @ImportanceOfBeingErnest, I was able to figure this out. In

fig, ax = plt.subplots(2,3,sharex=True, sharey=True, gridspec_kw={'width_ratios':[1,1,0.5]})

the widths of the axes are set up as desired. However, while my desired behavior of

axi = plt.subplot2grid((2,3),(0,2),rowspan=2)

was to span the entire third column of the existing subplots, in reality it creates a new virtual 2x3 grid with width ratios [1,1,1] and writes axes spanning the the right column of this new grid. Since this new right column is 1/3 of the figure width, it overlaps part of the center column of the original subplots, causing them to disappear.

The solution, in order to keep this to two lines of code, is to change the subplot2grid call to mimic the desired width ratios:

axi = plt.subplot2grid((2,5),(0,4),rowspan=2)

I arrived at 5 columns for the grid by transforming the original width_ratios vector: 2*[1,1,0.5] = [2,2,1] and sum([2,2,1]) = 5. Basically, since subplot2grid is unaware of the width_ratios specified in subplots, you have to force it to fit with a new grid calculation.

enter image description here