Skip to content

Add dataset line plot #4820

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

Draft
wants to merge 29 commits into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
3557771
Add dataset line plot
Illviljan Jan 17, 2021
fd822cd
Update dataset_plot.py
Illviljan Jan 17, 2021
516c0d0
Update dataset_plot.py
Illviljan Jan 17, 2021
da30687
Handle when hue is not None
Illviljan Jan 17, 2021
7127229
sort and add linewidth
Illviljan Jan 25, 2021
133ccd5
variant with dataarray
Illviljan Jan 26, 2021
295352a
Use the dataarray variant.
Illviljan Feb 8, 2021
798d2b9
Merge branch 'master' into Illviljan-dataset_line_plot
Illviljan Feb 12, 2021
4f1ddc2
copy doc from dataarray
Illviljan Feb 13, 2021
ed31db7
Update dataset_plot.py
Illviljan Feb 13, 2021
fb7e9db
Update dataset_plot.py
Illviljan Feb 13, 2021
e10d5ca
allow adding any number of extra coords
Illviljan Feb 14, 2021
474928f
Explain how ds will becom darray
Illviljan Feb 14, 2021
54bd639
Update dataset_plot.py
Illviljan Feb 14, 2021
f58c52a
Merge branch 'master' into Illviljan-dataset_line_plot
Illviljan Feb 19, 2021
a8edc08
Update dataset_plot.py
Illviljan Feb 19, 2021
9c416f2
use coords for coords
Illviljan Feb 20, 2021
3ade6c4
Merge branch 'master' into Illviljan-dataset_line_plot
Illviljan Apr 2, 2021
c14ae47
Merge branch 'master' into Illviljan-dataset_line_plot
Illviljan Apr 14, 2021
93b50e2
Merge branch 'master' into Illviljan-dataset_line_plot
Illviljan May 9, 2021
7110220
Explain goal of moving ds plots to da
Illviljan May 13, 2021
76d42e5
Merge branch 'master' into Illviljan-dataset_line_plot
Illviljan May 18, 2021
b8c749d
Merge branch 'main' into Illviljan-dataset_line_plot
Illviljan Jun 24, 2021
3e90c1f
Merge branch 'main' into Illviljan-dataset_line_plot
Illviljan Jul 18, 2021
bf8b0ea
handle non-existant coords
Illviljan Jul 20, 2021
424a006
Update dataset_plot.py
Illviljan Jul 20, 2021
fe5bece
Look through the kwargs to find extra coords
Illviljan Jul 20, 2021
5f57f5c
Merge branch 'main' into Illviljan-dataset_line_plot
Illviljan Jul 22, 2021
1dfad9f
improve ds to da wrapper
Illviljan Jul 24, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions xarray/plot/dataset_plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from ..core.alignment import broadcast
from .facetgrid import _easy_facetgrid
from .plot import _PlotMethods
from .utils import (
_add_colorbar,
_get_nice_quiver_magnitude,
Expand Down Expand Up @@ -622,3 +623,78 @@ def streamplot(ds, x, y, ax, u, v, **kwargs):

# Return .lines so colorbar creation works properly
return hdl.lines


def _attach_to_plot_class(plotfunc):
"""
Set the function to the plot class and add a common docstring.

Use this decorator when relying on DataArray.plot methods for
creating the Dataset plot.

TODO: Reduce code duplication.

* The goal is to reduce code duplication by moving all Dataset
specific plots to the DataArray side and use this thin wrapper to
handle the conversion between Dataset and DataArray.
* Improve docstring handling, maybe reword the DataArray versions to
explain Datasets better.
* Consider automatically adding all _PlotMethods to
_Dataset_PlotMethods.

Parameters
----------
plotfunc : function
Function that returns a finished plot primitive.
"""
# Build on the original docstring:
original_doc = getattr(_PlotMethods, plotfunc.__name__, None)
commondoc = original_doc.__doc__
if commondoc is not None:
doc_warning = (
f"This docstring was copied from xr.DataArray.plot.{original_doc.__name__}."
" Some inconsistencies may exist."
)
# Add indentation so it matches the original doc:
commondoc = f"\n\n {doc_warning}\n\n {commondoc}"
else:
commondoc = ""
plotfunc.__doc__ = (
f" {plotfunc.__doc__}\n\n"
" The y DataArray will be used as base,"
" any other variables are added as coords.\n\n"
f"{commondoc}"
)
Comment on lines +662 to +667
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding an explanation here how the dataset becomes a dataarray should help making sense of the autogenerated docs I think.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the _dsplot decorator not work for this case? It would help minimize the changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that the line plot comes from the dataarray side you don't have to do all the additional things _dsplot is doing. All that's really needed then is to attach to the plot class and then do this tweak to the docs so that they make more sense.

My end goal here is to move all the dataset specific plots to the dataarray side and use this thin wrapper for dataset plotting. Back when I started this PR in january there was only scatter so it made more sense back then.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Illviljan Can you add this to the docstring of _attach_to_plot_class

Let's also see what @mathause thinks...


@functools.wraps(plotfunc)
def plotmethod(self, *args, **kwargs):
return plotfunc(self._ds, *args, **kwargs)

# Add to class _PlotMethods
setattr(_Dataset_PlotMethods, plotmethod.__name__, plotmethod)


def _temp_dataarray(ds, y, args, kwargs):
"""Create a temporary datarray with extra coords."""
from ..core.dataarray import DataArray

# Base coords:
coords = dict(ds.coords)

# Add extra coords to the DataArray:
all_args = args + tuple(kwargs.values())
coords.update({v: ds[v] for v in all_args if ds.data_vars.get(v) is not None})

# The dataarray has to include all the dims. Broadcast to that shape
# and add the additional coords:
_y = ds[y].broadcast_like(ds)

return DataArray(_y, coords=coords)


@_attach_to_plot_class
def line(ds, x, y, *args, **kwargs):
"""Line plot Dataset data variables against each other."""
da = _temp_dataarray(ds, y, args, kwargs)

return da.plot.line(x, *args, **kwargs)