seaborn
seaborn copied to clipboard
Feature request: scatterplot, allow facecolor="none" and map the hue variable to edgecolor
It would be nice to have a simple way to specify hollow markers in seaborn.scatterplot()
. One could map the hue
variable to edgecolor
by default and add a facecolor
parameter.
Currently, adding a facecolor
parameter has no effect (probably because hue overrides?). Adding edgecolor
works only when "a valid single color nor a color sequence consisting of single character color" is specified.
I also tried circumventing this by changing the default settings as suggested in issue #1751 (using something like with sns.plotting_context(rc={"markerfacecolor": None}): ...
, but again it has no effect probably because hue overrides.
I had been thinking about supporting this by adding a hue_target
or similar parameter that could take face
or edge
, but this is a feasible alternate suggestion. I'd say it could go a bit further and map hue to the edges whenever facecolor
is specified at all. (I guess I can't think of an obvious case where that's necessary, but it seems like supporting the general case has no cost, sooo).
Another option would be to add fill={bool}
, which is how the distribution plots work. I think the implementation would be a bit simpler. It wouldn't let you map edge with a different face color, but maybe that isn't useful enough.
I'd want this to work consistently across all plots with artists that have facecolor/edgecolor, so barplot
, the categorical scatter plots, and others should be included in any work.
A relevant upstream issue is https://github.com/matplotlib/matplotlib/pull/17850. There are some significant complexities in matplotlib here to be aware of.
I'm going to close this as completed in the new objects interface. It's possible that it would get added to the plotting functions in the future as they get refactored to use the objects behind the scenes, but it's not explicitly planned as I'm not yet certain how much extra complexity should get packed into them.
Example with the new interface:
(
so.Plot(tips, "total_bill", "tip", color="day")
.add(so.Dot(fill=False, stroke=2, pointsize=8))
)
Or (for some reason) map the edge color but maintain a facecolor:
(
so.Plot(tips, "total_bill", "tip", edgecolor="day")
.add(so.Dot(color="w", edgewidth=2, pointsize=8))
)