Skip to content
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

Binned coordinates (pd.Interval) not plottable on the y-axis. #3571

Closed
juseg opened this issue Nov 25, 2019 · 1 comment · Fixed by #3685
Closed

Binned coordinates (pd.Interval) not plottable on the y-axis. #3571

juseg opened this issue Nov 25, 2019 · 1 comment · Fixed by #3685

Comments

@juseg
Copy link
Contributor

juseg commented Nov 25, 2019

Minimal Code Sample

import numpy as np
import xarray as xr
import matplotlib.pyplot as plt

# create fake data
data = xr.DataArray(np.random.rand(101)).rename('data')

# group by bins and compute sum
bins = np.linspace(0, 1, 11)
data = data.groupby_bins(data, bins).sum()

# plot group means
data.plot()                             # works
data.plot(x='data_bins')                # works
plt.plot((bins[:-1]+bins[1:])/2, data)  # works

# plot with axes transposed
data.plot(y='data_bins')                # TypeError
data.plot.line(y='data_bins')           # TypeError
plt.plot(data, (bins[:-1]+bins[1:])/2)  # workaround

Expected Output

I would like to plot binned data (produced with groupby_bins) with transposed axes, i.e. data on the x-axis, and bins on the y-axis.

Problem Description

Attempting to plot using an array of pd.Interval on the y-axis yields the following TypeError. The error message reports data should be numeric, dates or pd.Interval, which they are.

Traceback (most recent call last):
  File "./groupbybug.py", line 19, in <module>
    data.plot(y='data_bins')                # TypeError
  File "~/.local/lib/python3.7/site-packages/xarray/plot/plot.py", line 465, in __call__
    return plot(self._da, **kwargs)
  File "~/.local/lib/python3.7/site-packages/xarray/plot/plot.py", line 202, in plot
    return plotfunc(darray, **kwargs)
  File "~/.local/lib/python3.7/site-packages/xarray/plot/plot.py", line 323, in line
    _ensure_plottable(xplt_val, yplt_val)
  File "~/.local/lib/python3.7/site-packages/xarray/plot/utils.py", line 512, in _ensure_plottable
    "Plotting requires coordinates to be numeric "
TypeError: Plotting requires coordinates to be numeric or dates of type np.datetime64, datetime.datetime, cftime.datetime or pd.Interval.

Output of xr.show_versions()

INSTALLED VERSIONS

commit: None
python: 3.7.4 (default, Oct 4 2019, 06:57:26)
[GCC 9.2.0]
python-bits: 64
OS: Linux
OS-release: 4.19.84-1-MANJARO
machine: x86_64
processor:
byteorder: little
LC_ALL: None
LANG: fr_CH.utf8
LOCALE: fr_CH.UTF-8
libhdf5: 1.10.5
libnetcdf: 4.7.2

xarray: 0.14.1
pandas: 0.25.2
numpy: 1.17.3
scipy: 1.3.1
netCDF4: 1.5.3
pydap: None
h5netcdf: None
h5py: None
Nio: None
zarr: None
cftime: 1.0.4.2
nc_time_axis: None
PseudoNetCDF: None
rasterio: 1.1.0
cfgrib: None
iris: None
bottleneck: None
dask: 2.5.2
distributed: 0+untagged.1.gd096901.dirty
matplotlib: 3.1.1
cartopy: 0.17.0
seaborn: None
numbagg: None
setuptools: 41.2.0
pip: 19.2.3
conda: None
pytest: 5.2.1
IPython: 7.9.0
sphinx: 2.2.1

@dcherian
Copy link
Contributor

Thanks for the report @juseg. It looks like the logic here needs to be updated:

xarray/xarray/plot/plot.py

Lines 300 to 323 in ff6051d

if _valid_other_type(xplt.values, [pd.Interval]):
# Is it a step plot? (see matplotlib.Axes.step)
if kwargs.get("linestyle", "").startswith("steps-"):
xplt_val, yplt_val = _interval_to_double_bound_points(
xplt.values, yplt.values
)
# Remove steps-* to be sure that matplotlib is not confused
kwargs["linestyle"] = (
kwargs["linestyle"]
.replace("steps-pre", "")
.replace("steps-post", "")
.replace("steps-mid", "")
)
if kwargs["linestyle"] == "":
del kwargs["linestyle"]
else:
xplt_val = _interval_to_mid_points(xplt.values)
yplt_val = yplt.values
xlabel += "_center"
else:
xplt_val = xplt.values
yplt_val = yplt.values
_ensure_plottable(xplt_val, yplt_val)

Note that the 2D plotting functions do this:

xarray/xarray/plot/plot.py

Lines 697 to 698 in ff6051d

xplt, xlab_extra = _resolve_intervals_2dplot(xval, plotfunc.__name__)
yplt, ylab_extra = _resolve_intervals_2dplot(yval, plotfunc.__name__)

This should be relatively easy fix if you're up for it.

dcherian pushed a commit that referenced this issue Jan 22, 2020
* Allow binned coords on 1D plots y-axis. See #3571.

* Add helper to convert intervals for 1d plots.

* Add tests for line plots with x/y/x&y intervals.

* Add tests for step plots with x/y intervals.

* Simplify syntax in 1D intervals plot helper.

* Document new handling of y-axis intervals.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants