-
-
Notifications
You must be signed in to change notification settings - Fork 112
Implement interactive API for all data backends #505
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
Conversation
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.
Looks great! Would be nice to open an issue somewhere (I guess on hvplot) outlining what it would take to implement this outside of hvPlot and/or outside of HoloViews someday. (Not that I'm suggesting you actually do such an implementation, but it would be good to record for posterity what those possibilities are, so that people can evaluate those pros and cons in case there are opportunities to apply this approach in cases where HoloViews isn't an appropriate dependency. Plus those pros/cons might motivate splitting HoloViews into core and plotting, in some scenarios.)
return self._clone(transform) | ||
def __gt__(self, other): | ||
other = other._transform if isinstance(other, Interactive) else other | ||
transform = type(self._transform)(self._transform, operator.gt, other) |
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 there a way to avoid specifying each of these delegations explicitly like this? The answer may well be no, but it seems like a shame to have so much boilerplate code here, which makes it hard to see the real code, and would cover up any special processing that might be happening in one of these seemingly boilerplate methods.
hvplot/interactive.py
Outdated
transform = type(self._transform)(self._transform, operator.truediv, other, reverse=True) | ||
return self._clone(transform) | ||
|
||
def plot(self, *args, **kwargs): |
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.
Can you add a docstring explaining why plot
needed this special code? Does it mean that .interactive
won't work with other .plot-API packages like cufflinks/pdvega, and/or related packages like Plotly Express?
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'll add a comment, and no. It's really just matplotlib which has this implicit state nonsense, which requires me to work around. I also still have to add special handling for Pandas plot engines.
elif loc in ('left_top', 'right_top'): | ||
widgets = Column(widget_box, VSpacer()) | ||
elif loc in ('left_bottom', 'right_bottom'): | ||
widgets = Column(VSpacer(), widget_box) |
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.
Seems like this layout code ought to be pulled out into its own function to make this method shorter and easier to follow. Plus this functionality seems similar to interact
, DynamicMaps, and other cases where widgets are generated and added to a layout, and it would be nice to have a consistent approach for controlling those.
_patch_interactive.__doc__ = Interactive.__call__.__doc__ | ||
interactive_prop = property(_patch_plot) | ||
setattr(pd.DataFrame, name, interactive_prop) | ||
setattr(pd.Series, name, interactive_prop) |
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 there a supported way to make the interactive support available without import hvplot.pandas
or similar sideeffect-y imports? Personally, I'll use import hvplot.pandas
, but I'm curious if there is a more awkward but less magic alternative, either to explicitly perform the monkeypatching or to have a non-monkeypatch alternative (e.g. a global function instead of a method).
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.
Interactive(ds)
will work, I can also provide a helper to do the monkey-patching manually.
I want to include these in Intake plot specs, so that source.plot() can produce interactive things! |
Good question. Intake plot specs are YAML, like:
I would guess that it's already possible to get some limited interactivity, e.g. by adding Maybe some syntax like |
Something like this? slider = pn.widgets.IntSlider(name='time', start=0, end=10)
ds.air.interactive.isel(time=slider).plot() -> plots:
example:
kind: pipeline
pipeline:
- getattr: air
- isel:
time:
widget: IntSlider
name: time
start: 0
end: 10
plotargs: {} For the API, it'd also be great to be able to call with some value for the widgets to get the output data that would be plotted. That would also cover the "process my data in a pipeline" request that we've wondered about for a while (i.e., use this model even when there are no interactive elements). Of course, this is quite long and verbose, and maybe doesn't all belong in the "plots" section, especially if we want to make the derived data available. In short, I think it's all doable, we just have to decide what feels convenient for the user. |
bb16f17
to
853d9a1
Compare
853d9a1
to
4aed15c
Compare
Implements interactive API as described in pydata/xarray#3709.
Depends on holoviz/holoviews#4578