Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better support for faceted plots with plt.hexbin and plt.hist2d #321

Closed
shoyer opened this issue Oct 5, 2014 · 5 comments · Fixed by #2125
Closed

Better support for faceted plots with plt.hexbin and plt.hist2d #321

shoyer opened this issue Oct 5, 2014 · 5 comments · Fixed by #2125

Comments

@shoyer
Copy link
Contributor

shoyer commented Oct 5, 2014

Just to add two more items to my seaborn wish-list: It would great if FacetGrid and PairGrid worked well with hexbin and/or hist2d plots.

Hexbin

plt.hexbin works, but the defaults are so bad that you can barely tell:

import seaborn as sns
df = sns.load_dataset('iris')
g = sns.FacetGrid(df, col='species', hue='species')
g.map(plt.hexbin, 'sepal_length', 'petal_length')

image

Notice that by default edgecolor is controlled by the hue argument, which looks rather strange.

Tweaking some options makes a big difference (also solves the aesthetic issues in #271):

g.map(plt.hexbin, 'sepal_length', 'petal_length', gridsize=20, extent=[4, 8, 1, 7], edgecolor='none', mincnt=1)

image

Hist2D

g = sns.FacetGrid(df, col='species')
g.map(plt.hist2d, 'sepal_length', 'petal_length')

Nope!

AttributeError: Unknown property color

The culprit (also for the inability to control edgecolor with hexbin) is this line:
https://github.com/mwaskom/seaborn/blob/v0.4.0/seaborn/axisgrid.py#L418

If we move that statement inside the conditional on the next line (if self._hue_var is not None), then that solves the color issues with hexbin and I can get hist2d working. Again, the defaults are terrible:
image

When tweaked, it looks OK:

g = sns.FacetGrid(df, col='species')
g.map(plt.hist2d, 'sepal_length', 'petal_length', range=[[4, 8], [1, 7]], bins=[8, 6], cmin=1)

image

(Yes, matplotlib uses totally different keyword arguments in hexbin and hist2d for all the control nobs, even if they are basically equivalent.)

Action items

  1. Can we safely apply my suggested patch? I'm guessing it breaks something else but I haven't run it through the test-suite yet.
  2. How do you feel about tweaking defaults parameters based on the type of plot passed to FacetGrid.map? Perhaps the clearer solution is to write sns.binplot (mirroring sns.kdeplot) to provide a unified API with better defaults, which we could also use in sns.jointplot?
  3. Ideally FacetGrid should have some sort of logic to set the range/extent argument for all these plots together based on the shared x and y limits.
  4. Both these sorts of plots call for adding colorbar legends (see also feature request: colorbar for kdeplot #312, sns.PairGrid.add_legend() not leading to display of legend #313).
  5. In any case, I would love to add a few examples to show off these kinds of plots in the Seaborn gallery (it's not obvious they can be done now).
@mwaskom
Copy link
Owner

mwaskom commented Oct 5, 2014

Can we safely apply my suggested patch? I'm guessing it breaks something else but I haven't run it through the test-suite yet.

The one thing I would wonder about is that it would surrender control over colors to the axis color cycles. That might produce some surprising results, and currently when you map multiple kinds of plots they have the same color, which I think would no longer be the case. I'm also not sure if that will break lmplot assumptions, but it feels like it might.

How do you feel about tweaking defaults parameters based on the type of plot passed to FacetGrid.map? Perhaps the clearer solution is to write sns.binplot (mirroring sns.kdeplot) to provide a unified API with better defaults, which we could also use in sns.jointplot?

That feels messy, I think I would want to resist this as much as possible. The second solution seems a lot more workable and I agree more broadly useful (the default parameters for plt.hexbin are in general kind of bizarre).

Ideally FacetGrid should have some sort of logic to set the range/extent argument for all these plots together based on the shared x and y limits.

This feels similarly messy in terms of hardcoding assumptions about certain plot functions. I'd like to keep FacetGrid as agnostic to that kind of stuff as possible. But it's less clear what a good way to have smart extents by default would be.

Both these sorts of plots call for adding colorbar legends (see also #312, #313).

Ah, yes...

In any case, I would love to add a few examples to show off these kinds of plots in the Seaborn gallery (it's not obvious they can be done now).

👍

@mtzl
Copy link

mtzl commented Nov 2, 2016

Hi, has there been any developement on this? I've been running into the same issues.

Is there a preferred workaround other than the fix described above?

@mwaskom
Copy link
Owner

mwaskom commented Jun 13, 2020

With #2125:

g = sns.FacetGrid(penguins, col="species", hue="species")
g.map_dataframe(sns.histplot, x="culmen_length_mm", y="culmen_depth_mm")
g.set_axis_labels("Culmen length", "Culmen depth")

image

It doesn't do hexbin. I think that will be a different (new) function.

@shoyer
Copy link
Contributor Author

shoyer commented Jun 15, 2020

Gorgeous! Nice work @mwaskom !

@mwaskom
Copy link
Owner

mwaskom commented Jun 15, 2020

Also should note: that plot will soon be easier to make by doing something like

sns.distplot(
    data=penguins, x="culmen_length_mm", y="culmen_depth_mm",
    hue="species", col="species",
)

But that remains to be implemented.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants