8

The below code gives an error:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-14-ea5c06641335> in <module>()
     14 values = usa.loc[: , "GDP Billions"]
     15 
---> 16 fig, (ax1, ax2, ax3, ax4) = plt.subplots(2, 2, figsize=(15, 6))
     17 
     18 fig.suptitle('GDP Growth', fontsize=20)

ValueError: not enough values to unpack (expected 4, got 2)

If I change fig, (ax1, ax2, ax3, ax4) = plt.subplots(2, 2, figsize=(15, 6)) to fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6)) and delete the corresponding code for ax3 and ax4 below, it works as desired. Not sure why it is not working as written.

    %matplotlib inline
    import matplotlib.pyplot as plt
    import matplotlib.ticker
    import numpy as np
    from numpy import array

    plt.style.use('seaborn-white')

    plt.rc('ytick', labelsize=14) 
    plt.rc('xtick', labelsize=14) 

    # Plot GDP/Year
    names =  usa.loc[: , "Year"]
    values = usa.loc[: , "GDP Billions"]

    fig, (ax1, ax2, ax3, ax4) = plt.subplots(2, 2, figsize=(15, 6))

    fig.suptitle('GDP Growth', fontsize=20)

    ax1.plot(names, values)
    ax1.xaxis.set_ticks(np.arange(0, 57, 8))
    ax1.set_ylabel('GDP', fontsize=16)
    ax1.set_title('United States',fontsize=16)
    ax1.get_yaxis().set_major_formatter(matplotlib.ticker.FuncFormatter(lambda x, p: format(int(x), ',')))

    ax2.plot(names, values)
    ax2.xaxis.set_ticks(np.arange(0, 57, 8))
    ax2.set_ylabel('Year', fontsize=16)
    ax2.set_title('China',fontsize=16)
    ax2.get_yaxis().set_major_formatter(matplotlib.ticker.FuncFormatter(lambda x, p: format(int(x), ',')))

    ax3.plot(names, values)
    ax3.xaxis.set_ticks(np.arange(0, 57, 8))
    ax3.set_ylabel('GDP', fontsize=16)
    ax3.set_title('United States',fontsize=16)
    ax3.get_yaxis().set_major_formatter(matplotlib.ticker.FuncFormatter(lambda x, p: format(int(x), ',')))

    ax4.plot(names, values)
    ax4.xaxis.set_ticks(np.arange(0, 57, 8))
    ax4.set_ylabel('Year', fontsize=16)
    ax4.set_title('China',fontsize=16)
    ax4.get_yaxis().set_major_formatter(matplotlib.ticker.FuncFormatter(lambda x, p: format(int(x), ',')))

    plt.show()
Daniel Lenz
  • 3,334
  • 17
  • 36
user3504322
  • 545
  • 2
  • 5
  • 18

2 Answers2

19

plt.subplots() will give you a two-dimensional array of axes (2x2 in your case), hence you need to set this up as follows:

fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(
                                    ncols=2,
                                    nrows=2,
                                    figsize=(15, 6))

Alternatively, you can also use:

fig, axes = plt.subplots(
                     ncols=2,
                     nrows=2,
                     figsize=(15, 6))

ax1, ax2, ax3, ax4 = axes.flatten()
Daniel Lenz
  • 3,334
  • 17
  • 36
  • So when using this with seaborn, how does one specify the appropriate ax? When I specify ax1 and ax2 it works properly (as in `sns.distplot(data.x1, ax=ax1)`) but when I specify ax3 (as in `sns.jointplot(data.x3, ax=ax3)`, it throws the following error. `inner() got multiple values for argument 'ax'` Edit: Found the answer -- jointplot is a special example that creates its own ax instance. Answer here: https://stackoverflow.com/questions/47029479/inner-got-multiple-values-for-argument-ax?rq=1 Makes sense, since it's not inside an easy to manage box. – TheProletariat Oct 12 '19 at 17:11
0

Per the documentation subplots() will return the figure and then a single axis or an array of axes equal to the dimensions specified (2x2 in your case).

fig, ax = plt.subplots(2, 2, figsize=(15, 6))

The variable ax holds the axes you need. Access them by:

ax1, ax2, ax3, ax4 = ax.flatten()
Easton Bornemeier
  • 1,918
  • 8
  • 22