Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pandas plots on Seaborn FacetGrid

I have a problem in a Qt application when I attempt to plot my dataframe as an area plot with a time index using pandas plotting function in combination with Seaborn's FacetGrids. What happens is that a grid layout is correctly created, but the plots do not appear in these grids. Using a Seaborn plotting function works as expected, though.

I tried to figure out what's going on by isolating the drawing routines from the rest of my code, and I've found a rather unexpected behaviour as shown below (using ipython notebook):

%matplotlib inline

import pandas as pd
import seaborn as sns

df = pd.DataFrame({
        "Home": [76, 64, 38, 78, 63,    45, 32, 46, 13, 40],
        "Away": [55, 67, 70, 56, 59,    69, 72, 24, 45, 21],
        "Team": ["T1"] * 5 +            ["T2"] * 5,
        "Year": ["1991", "1992", "1993", "1994", "1995"] * 2})

Now, what I want to do is to draw two facets, one for each team. Each facet should show the 'Away' and 'Home' columns as two separate time series. In line with the suggestion in another question (Plotting time series using Seaborn FacetGrid), I wrote a function that calls the pandas plotting function for the subset passed to it by map_dataframe():

def plot_area(data, color):
    data[["Home", "Away"]].index = pd.to_datetime(data["Year"])
    data[["Home", "Away"]].plot(kind="area")

However, when using this function, the result is rather unexpected: the FacetGrid is created and initialized correctly, but the two calls to the pandas method do not use this grid as their plotting region, and they appear elsewhere.

g = sns.FacetGrid(df, col="Team")
g.map_dataframe(plot_area)

<seaborn.axisgrid.FacetGrid at 0x1a25110>

Screenshot of output:

In the post I linked above, @mwaskom notes that methods called in this way

must draw a plot on the "currently active" matplotlib Axes.

Perhaps that is the problem here? The code as such appears to be correct, because with a different plotting function, everything works as expected, e.g. with a sns.heatmap():

def plot_heatmap(data, color):
    sns.heatmap(data[["Home", "Away"]])    

g = sns.FacetGrid(df, col="Team")
g.map_dataframe(plot_heatmap)

<seaborn.axisgrid.FacetGrid at 0x4a6d110>

Screenshot of output:

So, my question boils down to this: how do I have to change the function plot_area() so that the axes produced by the pandas plotting function appear on the subplots created by Seaborn's FacetGrid?

(pandas version 0.16.0, Seaborn version 0.6.0, ipython 3.2.1, Python 2.7)

like image 231
Schmuddi Avatar asked Aug 20 '15 11:08

Schmuddi


1 Answers

The comment by mwaskom set me on the right track: I have to provide the current axes to the plot function (now this seems so obvious...). For future reference, this is a working solution to my problem:

def plot_area(data, color):
    data.index = pd.to_datetime(data["Year"])
    data[["Home", "Away"]].plot(kind="area", ax=plt.gca())

g = sns.FacetGrid(df, col="Team")
g.map_dataframe(plot_area)
like image 196
Schmuddi Avatar answered Nov 15 '22 13:11

Schmuddi