This question already has an answer here:
Some minimal code of what I'm working on. Some parameters may seem redundant, but I didn't bother removing all of them.
import matplotlib
import matplotlib.gridspec as gridspec
matplotlib.use("macosx")
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
def plot_overlaid_2d_hist(data,
plot_axis_x,
plot_axis_y,
plot_axis_x_lab,
plot_axis_y_lab,
group_by = "group_name"):
# don't mind this for now
df = data
# Figure aspect
w, h = plt.figaspect(1)
fig = plt.figure(figsize = (w, h))
# Count the number of groups to make plots for
n_groups = len(df.groupby(group_by))
gs = gridspec.GridSpec(nrows = n_groups, ncols = 1)
subplot_id = 0
# Reshape data to make it work
for name, group in df.groupby(group_by, sort = False):
# Initialize subplot
fig.add_subplot(gs[subplot_id, 0])
# Check if we get subplots with pyplot
if subplot_id == 0:
col = "red"
else:
col = "blue"
plt.plot(x, y, color = col)
# instantiate JointGrid
# g = sns.JointGrid(group[plot_axis_x],
# group[plot_axis_y],
# data = group,
# space = 0,
# xlim = (0, 1.2),
# ylim = (0, 1))
#
# # Fix labels
# g = g.set_axis_labels(xlabel = str(plot_axis_x_lab),
# ylabel = str(plot_axis_y_lab))
#
# # center scatter plot on top
# g = g.plot_joint(plt.scatter,
# s = 0.5,
# alpha = 1,
# linewidth = 1)
#
# # marginals plot
# g = g.plot_marginals(sns.distplot,
# kde = True,
# kde_kws = dict(linewidth = 2,
# alpha = 1,
# bw = "Scott"),
# hist_kws = dict(alpha = 1))
# Next plot in row +1
subplot_id += 1
# Output
plt.tight_layout() # Attempts to fix alignment of subplot layout and axis titles
plt.show()
# quick data to check if the plots end up where they should
x = [0.5, 0.5, 0.4, 0.4]
y = [0.6, 0.4, 0.3, 0.4]
grp = ["a", "a", "b", "b"]
df = pd.DataFrame({"x":x,
"y":y,
"grp": grp})
plot_overlaid_2d_hist(data = df,
group_by = "grp",
plot_axis_x_lab = "x",
plot_axis_y_lab = "x",
plot_axis_y = "x",
plot_axis_x = "x")
Running the code with all seaborn plots (g) commented out shows that it works fine for native pyplot, but when I add in the multi-part seaborn plots, they show up in separate figures. What I would like is to have each 2D-histogram-with-marginals-and-scatter populate their own gridspec row/column.
Seeing that this question has already been asked before here I moved this answer to the older question. I would like to delete it here, but cannot do so because it is accepted already.
As has been pointed out at several places (this question, also this issue) several of the seaborn commands create their own figure automatically. This is hardcoded into the seaborn code, so there is currently no way to produce such plots in existing figures. Those are
PairGrid
,FacetGrid
,JointGrid
,pairplot
,jointplot
andlmplot
.There is a seaborn fork available which would allow to supply a subplot grid to the respective classes such that the plot is created in a preexisting figure. To use this, you would need to copy the
axisgrid.py
from the fork to the seaborn folder. Note that this is currently restricted to be used with matplotlib 2.1 (possibly 2.0 as well).An alternative could be to create a seaborn figure and copy the axes to another figure. The principle of this is shown in this answer and could be extended to Searborn plots. The implementation is a bit more complicated that I had initially expected. The following is a class
SeabornFig2Grid
that can be called with a seaborn grid instance (the return of any of the above commands), a matplotlib figure and asubplot_spec
, which is a position of agridspec
grid.The usage of this class would look like this:
Note that there might be several drawbacks from copying axes and the above is not (yet) tested thoroughly.