0

I'm trying to create a subplot of subplots using Matplotlib's gridspec, namely a boxplot above a histogram. I have a pandas dataframe of quantitative data. I have this code:

import matplotlib.pyplot as plt
import seaborn as sns
import matplotlib.gridspec as gridspec

fig = plt.figure(figsize=(20, 20))
outer = fig.add_gridspec(6, 2, wspace=0.05, hspace=0.2)
a = 0

for i in range(6):
    for j in range(2):
        inner = outer[i, j].subgridspec(2, 1, wspace=0, hspace=0)
        axs = inner.subplots()
        
        for c, ax in np.ndenumerate(axs):
            sns.boxplot(data=data_quant, x=data_quant[data_quant.columns[a]], orient='h', ax=ax)
            data_quant[data_quant.columns[a]].hist(bins=50)
            ax.set(xticks=[])
            
        a += 1
        
plt.show()

And this is the result: Histogram and boxplot

My code is inspired by this: Histogram with Boxplot above in Python but obviously I'm not getting the same results, i.e., the histograms are upside down and the boxplot is way too large.

Any clues as to how to do it?

Juan Ayala
  • 3
  • 1
  • 3

1 Answers1

0

The code below incorporates the following changes:

  • The loop for c, ax in np.ndenumerate(axs): seems to draw the same two subsubplots twice. It has been replaced by drawing the boxplot on the upper subsubplot and the histogram on the lower.
  • The call to subgridspec sets height_ratios to let the boxplot occupy 15% of the height.
  • inner.subplots() now has sharex=True so both x-axes are synchronized.
  • fig.add_gridspec(...) sets narrower borders (left, right, bottom, top).
  • some dummy test data has been generated
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np

plt.style.use('ggplot')
data_quant = pd.DataFrame({col: np.random.randn(100, 10).cumsum(axis=0).ravel() for col in 'abcdefghijkl'})

fig = plt.figure(figsize=(20, 20))
outer = fig.add_gridspec(6, 2, wspace=0.05, hspace=0.2, left=0.03, right=0.98, bottom=0.03, top=0.98)
a = 0

for i in range(6):
    for j in range(2):
        inner = outer[i, j].subgridspec(2, 1, wspace=0, hspace=0, height_ratios=[0.15, 0.85])
        axs = inner.subplots(sharex=True)

        sns.boxplot(data=data_quant, x=data_quant[data_quant.columns[a]], orient='h', ax=axs[0])
        data_quant[data_quant.columns[a]].hist(bins=50, ax=axs[1])
        axs[1].set(xticks=[])
        # axs[1].invert_yaxis() # if you want the histogram upside down
        a += 1
plt.show()

subsubplots with combined boxplot and histograms

JohanC
  • 71,591
  • 8
  • 33
  • 66