Comments (8)
Thank you, good to know!
As for laboriousness, it's mostly just on a pedagogical level rather than a typing-lines level. If there were an so.axhline method, I could do it in the same way I do the rest of the graph. Since there's not, I need to introduce the whole fig thing and .on(fig) as concepts, which are different ways of approaching the graph-making.
from seaborn.
The tricky thing as I recall it is that sometimes you would want a horizontal or vertical rules to be dependent on the data, eg you might want to show a distribution and then draw a vertical line at its mean, and then do that when grouping by a color variable, etc.
I do also think that using matplotlib objects directly is an anti-pattern (currently necessary here, but the sign of a feature gap).
from seaborn.
Also, interaction with things like facet
may be very weird.
from seaborn.
I don't think there is anything planned in a near future for this. I have my own code to do this if you like, as thankfully the objects API is modular :
from dataclasses import dataclass
import matplotlib as mpl
from seaborn._marks.base import (
Mappable,
MappableColor,
MappableFloat,
MappableString,
Mark,
resolve_color,
resolve_properties,
)
from seaborn._stats.base import Stat
from seaborn._core.typing import Default
@dataclass
class StraightLine(Mark):
"""Object drawing an horizontal or vertical line using the axline.
Giving orient "x" will result in a vertical line.
"""
color: MappableColor = Mappable("C0")
alpha: MappableFloat = Mappable(1)
linewidth: MappableFloat = Mappable(rc="lines.linewidth")
linestyle: MappableString = Mappable(rc="lines.linestyle")
def _plot(self, split_gen, scales, orient):
for keys, data, ax in split_gen():
vals = resolve_properties(self, keys, scales)
vals["color"] = resolve_color(self, keys, scales=scales)
artist_kws = self.artist_kws.copy()
value = {"x": "y", "y": "x"}[orient]
xy1_dict = {value: float(data[value].to_numpy()), orient: 0}
xy2_dict = {value: float(data[value].to_numpy()), orient: 1}
ax.axline(
(xy1_dict["x"], xy1_dict["y"]),
(xy2_dict["x"], xy2_dict["y"]),
color=vals["color"],
linewidth=vals["linewidth"],
linestyle=vals["linestyle"],
**artist_kws,
)
def _legend_artist(self, variables, value, scales):
keys = {v: value for v in variables}
vals = resolve_properties(self, keys, scales)
vals["color"] = resolve_color(self, keys, scales=scales)
artist_kws = self.artist_kws.copy()
return mpl.lines.Line2D(
[],
[],
color=vals["color"],
linewidth=vals["linewidth"],
linestyle=vals["linestyle"],
**artist_kws,
)
I only use this when I want to plot an aggregate value though (e.g. mean or median), otherwise I use the axhline
matplotlib API directly which is more convenient (I am not sure why you feel its is more laborious). Also, this uses private attributes which may break in a future update.
from seaborn.
If there were an so.axhline method, I could do it in the same way I do the rest of the graph.
The question is : what exactly is it supposed to do ? The seaborn objects operate on the DataFrame; there is no reason to have one that plots an arbitrary value, and it is pretty weird semantically. This is why I only use my custom object when plotting aggregate value, which makes sense as seaborn can compute those using Stat
objects (avoiding the need for extra computations outside). Also, I personally use .on(fig)
or .on(ax)
all the time; it would make sense to me to introduce it as you basically need it if you want to interact with your figure in any way afterwards.
from seaborn.
That's interesting - given the so.Plot().add() structure, I have thought of the conceptual framing of .add() being that we are operating on the plot itself, rather than the data frame. In that context it would make intuitive sense that you could put things into .add() that are not reliant on the data itself.
from seaborn.
Yes, definitely, I think reference lines based on statistics like means (and potentially within groupings) and based on constants that are given meaning by the data but not necessarily calculated based on the data are both very common. In my experience using seaborn.objects
it's by far the most common thing I go back to matplotlib to add.
This is just an offhand thought but I wonder if a syntax-compatible way of doing this would be to treat the use of constants like this as a kind of aggregation/Stat. Like if I could do so.Plot().add(so.Line(), so.Agg('constant', 0))
. After all, I picked 0 based on its meaning relative to the data, even if the formula I used to do that in my head isn't something it would make sense to write a Python function to calculate - it's easier just to give it the answer.
from seaborn.
To be clear I don't think there are any conceptual problems with so.Rule
(which is the terminology I was planning on using) just some annoying things about supporting a mark that typically has a scalar parameterization (e.g. so.Rule(y=0)
) but sometimes will have one or more values derived from the data.
from seaborn.
Related Issues (20)
- `sns.relplot()` legend not showing marker `'x'`, `'+'`, '1', '2' etc. HOT 2
- Future deprecation of palette without hue - the proposed solution does not yield the same result HOT 2
- Relplot refline error in situations when using dataframes w/ duplicate indicies
- Geographic Filled KDE Plot HOT 5
- Figure in the plot is not showing in heatmap in 0.12.2,but everything works right in 0.9.0 HOT 1
- Split violin plots not working HOT 7
- Expose error estimators and other statistical summary measures used for plots which perform aggregation and error estimates HOT 1
- sns.regplot regression line fails with large values HOT 2
- Feature Request: Continuous axes heat map
- Incorrect errobar for drawstyle='steps-post' HOT 2
- Seaborn objects interface: Log transformed bar plot does not plot correctly HOT 1
- [Bug] Plotting categorical columns includes empty categories HOT 3
- inconsistent ability to use palette to set alpha HOT 6
- UNITS of colorbar in 2D KDE plot? HOT 4
- Issue with facet grid and legends HOT 2
- Overlaying Plots HOT 2
- Add a second legend in a strip plot within FacetGrid. Is it possible? HOT 1
- Violinplot breaks when `x` parameter is removed HOT 2
- AttributeError: module 'matplotlib.cm' has no attribute 'register_cmap' HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from seaborn.