GPB
GPB

Reputation: 2495

Two graphs, two axis, one figure....stumped.

I am trying to plot 2 separate graphs from a dataset which have different x and y ranges. I am confused about the interaction between plt.figure, plt.subplot and plt.axes.

Assume I am attempting to plot lines which represent an value ("ROI") for different characteristics (loans characterized by letters A - G) for different terms of loans('term'). The range of 'issue date' is different for each loan term (e.g., for term = 36, loans have been originated since 2007, for term = 60, loans have been only originated since 2011).

Here's some pseudo-code for what I have.

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from itertools import groupby

alpha_grades = ('A','B','C','D','E','F','G')

color_scheme = {'A':'b','B':'g','C':'r','D':'c','E':'m','F':'y','G':'k'}

for term in [36,60]:
    for grade in alpha_grades:
        if ( term == 36 ):
            plt.figure(1,figsize=(12,9))
        else:
            plt.figure(2,figsize=(12,9))

    df[(df['grade'] == grade) & (df['term']==term)].groupby(
        'issue_date')['ROI'].mean().plot(color=color_scheme[grade],label = ("Grade: %s" % grade))
    plt.legend(loc=2)
    title = ("%i Mo Lending Rate by Rating" % term)
    plt.title(title)

The screen and file output for this current iteration sizes the first graph (term ==36) much smaller than the second. I thought by defining 2 separate figures with the same fig size I could get away from that?

Thanks in advance for any help!

Upvotes: 3

Views: 471

Answers (1)

TheBlackCat
TheBlackCat

Reputation: 10298

A figure is basically a window. That window can have one or more axes, where each axes is a plot. plt.subplot lets you create multiple axes in a figure. Both a figure and an axes are objects, with their own methods. For example, plt.plot is just a thing wrapper around an axes object's plot method.

In your case you don't want to call any of these directory. Instead, you should call plt.subplots() (note the "s" at the end). This a convenience function that will create a figure, put one are more axes in that figure, and then return both the figure and all the axes. You can then pass the axes to the pandas plot function to force it to plot on that axes. You can also call set the legend, and title for that axes, but it is probablz easier to do that inside pandas.

So something like this should work (I simplified a few things as well):

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from itertools import groupby

alpha_grades = ('A','B','C','D','E','F','G')

color_scheme = {'A':'b','B':'g','C':'r','D':'c','E':'m','F':'y','G':'k'}

fig1, ax1 = plt.subplots(figsize=(12,9)) # same as plt.subplots(1, 1)
fig2, ax2 = plt.subplots(figsize=(12,9))

for term, ax in zip([36,60], [ax1, ax2]):
    ax.hold(True)
    for grade, color in color_scheme.items():
        df2 = df[(df['grade'] == grade) & (df['term']==term)]
        df3 = groupby('issue_date')['ROI'].mean()
        df3.plot(ax=ax, color=color, 
                 label=("Grade: %s" % grade))
    ax.hold(False)
    ax.legend(loc=2)
    ax.set_title("%i Mo Lending Rate by Rating" % term)

fig1.show()
fig2.show()

Note that, rather than using plt, you are interacting with the figure and axes directly.

If you want to put both plots in a single figure, say one on the left and one on the right, you can do something like this:

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from itertools import groupby

alpha_grades = ('A','B','C','D','E','F','G')

color_scheme = {'A':'b','B':'g','C':'r','D':'c','E':'m','F':'y','G':'k'}

fig, axs = plt.subplots(1, 2, figsize=(12*2,9))  # creates two axes

for term, ax in zip([36,60], axs):
    ax.hold(True)
    for grade, color in color_scheme.items():
        df2 = df[(df['grade'] == grade) & (df['term']==term)]
        df3 = groupby('issue_date')['ROI'].mean()
        df3.plot(ax=ax, color=color, 
                 label=("Grade: %s" % grade))
    ax.hold(False)
    ax.legend(loc=2)
    ax.set_title("%i Mo Lending Rate by Rating" % term)

fig.show()

Upvotes: 3

Related Questions