hvplot icon indicating copy to clipboard operation
hvplot copied to clipboard

Default xarray coordinates not inferred when non-dimension coordinates in data array.

Open relativistic opened this issue 2 years ago • 1 comments

The following plots as I would expect:

da = xr.DataArray(np.arange(9).reshape(3,3), dims=['x','y'], )
da.hvplot.image()

bokeh_plot (16)

However, if I add non-dimension coordinates, I can no longer plot the data (even though the plotting method does not use the non-dimensioned coordinates the way I'm plotting here). The following throws a DataError:

da = xr.DataArray(np.arange(9).reshape(3,3), dims=['x','y'], 
                  coords={'lat':('x',[4,5,6])}
                 )
da.hvplot.image()

I would expect it to behave the same as if there were no non-dimensioned coordinates present. Note that the native xarray plotting library works as expected:

da.plot()

image

Interestingly, if I supply x and y explicitly, I can plot. Thefollowing works as expected:

da = xr.DataArray(np.arange(9).reshape(3,3), dims=['x','y'], 
                  coords={
                      'x': np.arange(3),
                      'y':np.arange(3),
                      'lat':('x',[4,5,6])
                  }
                 )
da.hvplot.image()

So a good workaround for now is to explicitly define dimensioned coordinates.

Context: Where I naturally wind up with "implied" coordinates is after I do a reset_index() operation on a multi_index. hvplot and to_netcdf() don't seem to handle multi-indices well, so I find myself doing a reset index after any stacking or other operations that result in a MultiIndex.

Software versions I'm using:

  • xarray 0.20.1
  • holoviews 1.14.8
  • hvplot 0.7.3
  • numpy 1.20.3
  • bokeh 2.4.2
  • python 3.9.9

Details of the error thrown by .hvplot.image(): It gives the error:

---------------------------------------------------------------------------
DataError                                 Traceback (most recent call last)
/tmp/ipykernel_3140218/2186427060.py in <module>
      4 
      5 
----> 6 da.hvplot.image()

~/anaconda3/envs/soundcheck_py39/lib/python3.9/site-packages/hvplot/plotting/core.py in image(self, x, y, z, colorbar, **kwds)
    646             The HoloViews representation of the plot.
    647         """
--> 648         return self(x, y, z=z, kind='image', colorbar=colorbar, **kwds)
    649 
    650     def rgb(self, x=None, y=None, z=None, bands=None, **kwds):

~/anaconda3/envs/soundcheck_py39/lib/python3.9/site-packages/hvplot/plotting/core.py in __call__(self, x, y, kind, **kwds)
     77                 return pn.panel(plot, **panel_dict)
     78 
---> 79         return self._get_converter(x, y, kind, **kwds)(kind, x, y)
     80 
     81     def _get_converter(self, x=None, y=None, kind=None, **kwds):

~/anaconda3/envs/soundcheck_py39/lib/python3.9/site-packages/hvplot/converter.py in __call__(self, kind, x, y)
   1128                     else:
   1129                         name = data.name or self.label or self.value_label
-> 1130                         dataset = Dataset(data, self.indexes, name)
   1131                 else:
   1132                     try:

~/anaconda3/envs/soundcheck_py39/lib/python3.9/site-packages/holoviews/core/data/__init__.py in __init__(self, data, kdims, vdims, **kwargs)
    339 
    340         validate_vdims = kwargs.pop('_validate_vdims', True)
--> 341         initialized = Interface.initialize(type(self), data, kdims, vdims,
    342                                            datatype=kwargs.get('datatype'))
    343         (data, self.interface, dims, extra_kws) = initialized

~/anaconda3/envs/soundcheck_py39/lib/python3.9/site-packages/holoviews/core/data/interface.py in initialize(cls, eltype, data, kdims, vdims, datatype)
    254                 continue
    255             try:
--> 256                 (data, dims, extra_kws) = interface.init(eltype, data, kdims, vdims)
    257                 break
    258             except DataError:

~/anaconda3/envs/soundcheck_py39/lib/python3.9/site-packages/holoviews/core/data/xarray.py in init(cls, eltype, data, kdims, vdims)
    206             raise TypeError('Data must be be an xarray Dataset type.')
    207         elif not_found:
--> 208             raise DataError("xarray Dataset must define coordinates "
    209                             "for all defined kdims, %s coordinates not found."
    210                             % not_found, cls)

DataError: xarray Dataset must define coordinates for all defined kdims, [Dimension('y')] coordinates not found.

XArrayInterface expects gridded data, for more information on supported datatypes see http://holoviews.org/user_guide/Gridded_Datasets.html

relativistic avatar Apr 08 '22 23:04 relativistic

Thanks for reporting this issue. I'll just share a snippet that reproduces the DataError with some pure HoloViews code. I think that, if possible, we should align .hvplot() with xarray's .plot().

import holoviews as hv
import numpy as np
import xarray as xr

da = xr.DataArray(np.arange(9).reshape(3,3), dims=['x','y'], coords={'lat':('x', [4,5,6])}, name='value')

hv.Dataset(da, kdims=['x', 'y'])
---------------------------------------------------------------------------
DataError                                 Traceback (most recent call last)
/var/folders/c9/s6_8wl553ql93tjgvmbmsn5h0000gp/T/ipykernel_74343/1739244852.py in <module>
----> 1 hv_ds = hv.Dataset(da, kdims=['x', 'y'])

~/work/dev/holoviews/holoviews/core/data/__init__.py in __init__(self, data, kdims, vdims, **kwargs)
    337         validate_vdims = kwargs.pop('_validate_vdims', True)
    338         initialized = Interface.initialize(type(self), data, kdims, vdims,
--> 339                                            datatype=kwargs.get('datatype'))
    340         (data, self.interface, dims, extra_kws) = initialized
    341         super(Dataset, self).__init__(data, **dict(kwargs, **dict(dims, **extra_kws)))

~/work/dev/holoviews/holoviews/core/data/interface.py in initialize(cls, eltype, data, kdims, vdims, datatype)
    252                 continue
    253             try:
--> 254                 (data, dims, extra_kws) = interface.init(eltype, data, kdims, vdims)
    255                 break
    256             except DataError:

~/work/dev/holoviews/holoviews/core/data/xarray.py in init(cls, eltype, data, kdims, vdims)
    206             raise DataError("xarray Dataset must define coordinates "
    207                             "for all defined kdims, %s coordinates not found."
--> 208                             % not_found, cls)
    209 
    210         for vdim in vdims:

DataError: xarray Dataset must define coordinates for all defined kdims, [Dimension('y')] coordinates not found.

XArrayInterface expects gridded data, for more information on supported datatypes see http://holoviews.org/user_guide/Gridded_Datasets.html

maximlt avatar May 02 '22 15:05 maximlt