Adding figures with gridspec

Question:

I am trying to create a plot similar to the one from
this question.

Why am I only getting two pannels, i.e. just gs2:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec

def main():
   fig = plt.figure()
   gs1 = gridspec.GridSpec(1,4)
   gs2 = gridspec.GridSpec(2,4)

   for n in range(4):
      ax00 = plt.subplot(gs1[0,n])
      ax10 = plt.subplot(gs2[0,n])
      ax11 = plt.subplot(gs2[1,n])

      ax00.plot([0,0],[0,1*n],color='r')
      ax10.plot([0,1],[0,2*n],color='b')
      ax11.plot([0,1],[0,3*n],color='g')
   plt.show()

main()

which gives me this:

enter image description here

In the end I’d like to have a figure like:

enter image description here

which I obtained using the the code at the end of the questions. However I’d like to have the movability of the plots, which gs2.update(hspace=0) gives (the reason why i tried using gridspec). I.e. I’d like to remove the space between the last and second row.

def whatIwant():
    f, axarr = plt.subplots(3,4)

    for i in range(4):
        axarr[0][i].plot([0,0],[0,1*i],color='r')
        axarr[1][i].plot([0,1],[0,2*i],color='b') #remove the space between those and be able to move the plots where I want
        axarr[2][i].plot([0,1],[0,3*i],color='g')
    plt.show()
Asked By: Sebastiano1991

||

Answers:

This would indeed be one of the cases, where it makes sense to use a GridSpecFromSubplotSpec. That is, you’d create an overall GridSpec with one column and 2 rows (and a 1 to 2 height ratio). In the first row you’d put a GridSpecFromSubplotSpec with one row and 4 columns. In the second row you’d put one with two rows and 4 columns, additionally specifying an hspace=0.0 such that the two bottom rows do not have any spacing between them.

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec


fig = plt.figure()

gs = gridspec.GridSpec(2, 1, height_ratios=[1,2])
gs0 = gridspec.GridSpecFromSubplotSpec(1, 4, subplot_spec=gs[0], wspace=0.4)
gs1 = gridspec.GridSpecFromSubplotSpec(2, 4, subplot_spec=gs[1], hspace=0.0, wspace=0.4)

for n in range(4):
    ax00 = plt.subplot(gs0[0,n])
    ax10 = plt.subplot(gs1[0,n])
    ax11 = plt.subplot(gs1[1,n], sharex=ax10)
    plt.setp(ax10.get_xticklabels(), visible=False)
    ax00.plot([0,0],[0,1*n],color='r')
    ax10.plot([0,1],[0,2*n],color='b')
    ax11.plot([0,1],[0,3*n],color='g')
plt.show()

enter image description here

The advantage of this solution as opposed to the one in the linked question’s answer is that you do not overlapping GridSpecs and thus do not need to think about how they relate to each other.


In case you’re still interested in why the code from the question did not work:
You would need to use two different GridSpecs with each having the total amount of rows (in this case 3); but then only populating the first row of the first GridSpec and the second two rows of the second GridSpec:

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec

def main():
    fig = plt.figure()
    gs1 = gridspec.GridSpec(3,4)
    gs2 = gridspec.GridSpec(3,4, hspace=0.0)

    for n in range(4):
        ax00 = plt.subplot(gs1[0,n])
        ax10 = plt.subplot(gs2[1,n])
        ax11 = plt.subplot(gs2[2,n])

        ax00.plot([0,0],[0,1*n],color='r')
        ax10.plot([0,1],[0,2*n],color='b')
        ax11.plot([0,1],[0,3*n],color='g')
    plt.show()

main()