xarray icon indicating copy to clipboard operation
xarray copied to clipboard

Plotting empty DataArray oddly raises ImportError

Open derhintze opened this issue 1 year ago • 7 comments

What happened?

When calling the xarray.DataArray.plot() method on empty DataArrays raises an ImportError about a required, but missing, nc-time-axis package. This is at least confusing.

What did you expect to happen?

Either a more appropriate exception (to the effect of "don't try to plot nothing plz"). Or just get an empty plot returned.

Minimal Complete Verifiable Example

>>> import xarray as xr
>>> xr.DataArray([])
<xarray.DataArray (dim_0: 0)>
array([], dtype=float64)
Dimensions without coordinates: dim_0
>>> xr.DataArray([]).plot()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "foo/env/lib/python3.9/site-packages/xarray/plot/plot.py", line 866, in __call__
    return plot(self._da, **kwargs)
  File "foo/env/lib/python3.9/site-packages/xarray/plot/plot.py", line 332, in plot
    return plotfunc(darray, **kwargs)
  File "foo/env/lib/python3.9/site-packages/xarray/plot/plot.py", line 438, in line
    _ensure_plottable(xplt_val, yplt_val)
  File "foo/env/lib/python3.9/site-packages/xarray/plot/utils.py", line 648, in _ensure_plottable
    raise ImportError(
ImportError: Plotting of arrays of cftime.datetime objects or arrays indexed by cftime.datetime objects requires the optional `nc-time-axis` (v1.2.0 or later) package.

MVCE confirmation

  • [X] Minimal example — the example is as focused as reasonably possible to demonstrate the underlying issue in xarray.
  • [X] Complete example — the example is self-contained, including all data and the text of any traceback.
  • [ ] Verifiable example — the example copy & pastes into an IPython prompt or Binder notebook, returning the result.
  • [X] New issue — a search of GitHub Issues suggests this is not a duplicate.

Relevant log output

No response

Anything else we need to know?

No response

Environment

INSTALLED VERSIONS ------------------ commit: None python: 3.9.10 (main, Mar 15 2022, 15:56:56) [GCC 7.5.0] python-bits: 64 OS: Linux OS-release: 3.10.0-1160.49.1.el7.x86_64 machine: x86_64 processor: x86_64 byteorder: little LC_ALL: None LANG: en_US.UTF-8 LOCALE: ('en_US', 'UTF-8') libhdf5: 1.12.0 libnetcdf: 4.7.4

xarray: 0.21.1 pandas: 1.4.0 numpy: 1.21.5 scipy: 1.8.1 netCDF4: 1.5.8 pydap: None h5netcdf: None h5py: None Nio: None zarr: None cftime: 1.5.2 nc_time_axis: None PseudoNetCDF: None rasterio: None cfgrib: None iris: None bottleneck: None dask: None distributed: None matplotlib: 3.5.1 cartopy: None seaborn: None numbagg: None fsspec: None cupy: None pint: None sparse: None setuptools: 49.2.1 pip: 22.2.2 conda: None pytest: 7.1.2 IPython: 8.0.1 sphinx: None

derhintze avatar Oct 12 '22 08:10 derhintze

👁️ @headtr1ck

derhintze avatar Oct 12 '22 08:10 derhintze

Thanks for the bug report @derhintze !

I'm confused as to why this wasn't caught by our tests - I thought we had a minimum-dependencies test run in our suite :confused:

TomNicholas avatar Oct 12 '22 18:10 TomNicholas

the issue is that we only have a minimum dependencies CI (i.e. pandas and numpy but not matplotlib) and one that tests all dependencies with minimum versions. This means that we don't have an environment could have caught this (we'd need one with matplotlib but not nc-time-axis). This case is one of the issues we run into with so many optional dependencies: we can't just test every combination of them (the "all but dask" CI is an exception).

keewis avatar Oct 12 '22 19:10 keewis

I don't think we have a test for plotting empty DataArrays, so no combination of dependencies would've picked that up?

We should just explicitly check for da.size > 0 before trying anything in .plot

dcherian avatar Oct 12 '22 19:10 dcherian

pandas raises an error when plotting an empty dataframe:

import pandas as pd

a = pd.DataFrame()

a.plot()
Traceback (most recent call last):

  File "C:\Users\J.W\AppData\Local\Temp\ipykernel_14580\3422621525.py", line 1, in <cell line: 1>
    a.plot()

  File "C:\Users\J.W\anaconda3\envs\xarray-tests\lib\site-packages\pandas\plotting\_core.py", line 1001, in __call__
    return plot_backend.plot(data, kind=kind, **kwargs)

  File "C:\Users\J.W\anaconda3\envs\xarray-tests\lib\site-packages\pandas\plotting\_matplotlib\__init__.py", line 71, in plot
    plot_obj.generate()

  File "C:\Users\J.W\anaconda3\envs\xarray-tests\lib\site-packages\pandas\plotting\_matplotlib\core.py", line 451, in generate
    self._compute_plot_data()

  File "C:\Users\J.W\anaconda3\envs\xarray-tests\lib\site-packages\pandas\plotting\_matplotlib\core.py", line 636, in _compute_plot_data
    raise TypeError("no numeric data to plot")

TypeError: no numeric data to plot

Illviljan avatar Oct 12 '22 21:10 Illviljan

pandas raises an error when plotting an empty dataframe:

...
TypeError: no numeric data to plot

Not sure if TypeError is correct? Should it not be a ValueError?

headtr1ck avatar Oct 12 '22 21:10 headtr1ck

This is raised by matplotlib, not pandas. Personally, I prefer aligning with upstream projects, so I'd pick that very same error.

One could argue that it's a ValueError in the sense that there's no data to plot, which is like an invalid value. But I also could see why they picked TypeError, because one could have non-numeric (but not empty) data. But yeah, this is nitpicking, I suppose 😆

derhintze avatar Oct 13 '22 06:10 derhintze