-
-
Notifications
You must be signed in to change notification settings - Fork 26.2k
[MRG] ENH Improves on the plotting api by storing weak ref to display in axes #15702
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
base: main
Are you sure you want to change the base?
[MRG] ENH Improves on the plotting api by storing weak ref to display in axes #15702
Conversation
Does this also allow to pass a |
For this specific case, if the object was drawn on by a If it was drawn on by a normal plot function, it will error. For example: fig, ax = pyplot.subplots()
ax.plot([0, 1, 2], [1, 2, 3])
plot_partial_dependence(..., ax=ax) |
Is it reasonable to store the display object as an attribute of the The display objects stores all the data which can get pretty big. You would expect that the data can be GCed if the Display object isn't there anymore. But with this PR, the data exists as long as |
If we can, it would be ideal to also support that case fig, ax = pyplot.subplots()
ax.plot([0, 1, 2], [1, 2, 3])
plot_partial_dependence(..., ax=ax) This is typically useful if you want to plot the data points and then the PDPs on top, as done in #15582 (comment) |
Yes I have to make sure the axes is a weak reference. |
As in the axes has a weak reference to the display object. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some comments.
Sorry if I'm missing something but I don't see where the weak ref is being created? (this should also be tested)
sklearn/utils/_plot.py
Outdated
for used_attr in used_attrs: | ||
if hasattr(ax, used_attr) and getattr(ax, used_attr): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this equivalent to simply if any(getattr(...., None) for attr in used_attrs)
?
sklearn/utils/_plot.py
Outdated
"""Return true if the axes has been used""" | ||
used_attrs = ['lines', 'patches', 'texts', 'tables', 'artists', | ||
'tables', 'images'] | ||
msg = "The ax was already used in another plot function" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a matplotlib plot function or one of scikit-learn's? (same for docstring)
if hasattr(ax, "_sklearn_display_object"): | ||
if not isinstance(ax._sklearn_display_object, self.__class__): | ||
raise ValueError("The ax was already used by another " | ||
"display object") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should say "by another display object which is not an instance of self.class.name"
I was just thinking about the weakref on the train. I am going to move this back to WIP for a little bit. thank you for the early reviews. |
Supporting this can run into an unclear API. For example: fig, ax = pyplot.subplots()
ax.plot([0, 1, 2], [1, 2, 3])
plot_partial_dependence(est, features=[0, 1, 2], ax=ax) For this case, I do not think a user would want the first call to plot to be used in all 3 partial dependence plots. The only case where this can make sense is when there is only one feature: fig, ax = pyplot.subplots()
ax.plot([0, 1, 2], [1, 2, 3])
plot_partial_dependence(est, features=[0], ax=ax) I am -0.2 on this. It will lead to another code path to handle |
Please ping when ready @thomasjpfan . Also, I was looking at pandas internal: when you pass import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
d = {'a': np.arange(10),
'b': np.arange(10) + 23 * 4}
fig, ax = plt.subplots()
df = pd.DataFrame(d)
df.plot(subplots=True, ax=ax) # ask for subplots but also for a single ax => warning
plt.show() |
@NicolasHug This is ready for another review. I slightly prefer the current behavior where we do not clear the axes and raise an error if the axes has been used. If we relax this restriction and automatically clear the axes with a warning, there will be code out there that depends on this behavior. |
please refresh my memory: if I pass an array-like as In retrospect I'm not even sure we want to raise errors/warnings. |
If there as an array like of ax with stuff already drawn on, it will raise an error if the number of axes in the array like is not the expected number of axes. If it has the expected number of axes, then they will be drawn on directly. #15760 provides a better solution to how |
Reference Issues/PRs
Resolves #15581 (better)
What does this implement/fix? Explain your changes.
After a discussion with @tacaswell, it was concluded that adding attribute to the axes would be solution to figuring out
This allows use cases in #15581 to work:
Any other comments?
Storing the display object in the axes so it can be referenced later is a small hack, but it improves the API quite a bit.
CC @tacaswell @amueller @NicolasHug @glemaitre @qinhanmin2014