11

I have three different data sets where I produce a facetplot, each

a = sns.FacetGrid(data1, col="overlap",  hue="comp")
a = (g.map(sns.kdeplot, "val",bw=0.8))

b = sns.FacetGrid(data2, col="overlap",  hue="comp")
b = (g.map(sns.kdeplot, "val",bw=0.8))

c = sns.FacetGrid(data3, col="overlap",  hue="comp")
c = (g.map(sns.kdeplot, "val",bw=0.8))

Each of those plots has three subplots in one row, so in total I have nine plots.

I would like to combine these plots, in a subplots setting like this

f, (ax1, ax2, ax3) = plt.subplots(3,1)
ax1.a
ax2.b
ax3.c

How can I do that?

ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
spore234
  • 3,550
  • 6
  • 50
  • 76

1 Answers1

8

A FacetGrid creates its own figure. Combining several figures into one is not an easy task. Additionally, there is no such thing as subplot rows which can be added to a figure. So one would need to manipulate the axes individually.

That said, it might be easier to find workarounds. E.g. if the dataframes to show have the same structure as it seems to be from the question code, one can combine the dataframes into a single frame with a new column and use this as the row attribute of the facet grid.

import numpy as np; np.random.seed(3)
import pandas as pd
import seaborn.apionly as sns
import matplotlib.pyplot as plt

def get_data(n=266, s=[5,13]):
    val = np.c_[np.random.poisson(lam=s[0], size=n),
                np.random.poisson(lam=s[1], size=n)].T.flatten()
    comp = [s[0]]*n +  [s[1]]*n
    ov = np.random.choice(list("ABC"), size=2*n)
    return pd.DataFrame({"val":val, "overlap":ov, "comp":comp})

data1 = get_data(s=[9,11])
data2 = get_data(s=[7,19])
data3 = get_data(s=[1,27])

#option1 combine
for i, df in enumerate([data1,data2,data3]):
    df["data"] = ["data{}".format(i+1)] * len(df)

data = data1.append(data2)
data = data.append(data3)

bw = 2
a = sns.FacetGrid(data, col="overlap",  hue="comp", row="data")
a = (a.map(sns.kdeplot, "val",bw=bw ))
plt.show()

enter image description here

You can also loop over the dataframes and axes to obtain the desired result.

import numpy as np; np.random.seed(3)
import pandas as pd
import seaborn.apionly as sns
import matplotlib.pyplot as plt

def get_data(n=266, s=[5,13]):
    val = np.c_[np.random.poisson(lam=s[0], size=n),
                np.random.poisson(lam=s[1], size=n)].T.flatten()
    comp = [s[0]]*n +  [s[1]]*n
    ov = np.random.choice(list("ABC"), size=2*n)
    return pd.DataFrame({"val":val, "overlap":ov, "comp":comp})

data1 = get_data(s=[9,11])
data2 = get_data(s=[7,19])
data3 = get_data(s=[1,27])

#option2 plot each subplot individually
data = [data1,data2,data3]
bw = 2
fig, axes = plt.subplots(3,3, sharex=True, sharey=True)
for i in range(3):
    for j in range(3):
        x = data[i]
        x = x[x["overlap"] == x["overlap"].unique()[j]]
        for hue in x["comp"].unique():
            d = x[x["comp"] == hue]
            sns.kdeplot(d["val"], ax=axes[i,j], bw=bw, label=hue )

plt.show()

enter image description here

ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712