Skip to content

interp and reindex should work for 1d -> nd indexing #3252

@shoyer

Description

@shoyer

This works with isel and sel (see below). There's no particular reason why it can't work with reindex and interp, too, though we would need to implement our own vectorized version of linear interpolation (should not be too bad, it's mostly a matter of indexing twice and calculating weights from the difference in coordinate values).

Apparently this is quite important for vertical regridding in weather/climate science (cc @rabernat, @nbren12 )

In [35]: import xarray as xr

In [36]: import numpy as np

In [37]: data = xr.DataArray(np.arange(12).reshape((3, 4)), [('x', np.arange(3)), ('y', np.arange(4))])

In [38]: ind = xr.DataArray([[0, 2], [1, 0], [1, 2]], dims=['x', 'z'], coords={'x': [0, 1, 2]})

In [39]: data
Out[39]:
<xarray.DataArray (x: 3, y: 4)>
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
Coordinates:
  * x        (x) int64 0 1 2
  * y        (y) int64 0 1 2 3

In [40]: ind
Out[40]:
<xarray.DataArray (x: 3, z: 2)>
array([[0, 2],
       [1, 0],
       [1, 2]])
Coordinates:
  * x        (x) int64 0 1 2
Dimensions without coordinates: z

In [41]: data.isel(y=ind)
Out[41]:
<xarray.DataArray (x: 3, z: 2)>
array([[ 0,  2],
       [ 5,  4],
       [ 9, 10]])
Coordinates:
  * x        (x) int64 0 1 2
    y        (x, z) int64 0 2 1 0 1 2
Dimensions without coordinates: z

In [42]: data.sel(y=ind)
Out[42]:
<xarray.DataArray (x: 3, z: 2)>
array([[ 0,  2],
       [ 5,  4],
       [ 9, 10]])
Coordinates:
  * x        (x) int64 0 1 2
    y        (x, z) int64 0 2 1 0 1 2
Dimensions without coordinates: z

In [43]: data.interp(y=ind)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-43-e6eb7e39fd31> in <module>
----> 1 data.interp(y=ind)

~/dev/xarray/xarray/core/dataarray.py in interp(self, coords, method, assume_sorted, kwargs, **coords_kwargs)
   1303             kwargs=kwargs,
   1304             assume_sorted=assume_sorted,
-> 1305             **coords_kwargs
   1306         )
   1307         return self._from_temp_dataset(ds)

~/dev/xarray/xarray/core/dataset.py in interp(self, coords, method, assume_sorted, kwargs, **coords_kwargs)
   2455                     }
   2456                     variables[name] = missing.interp(
-> 2457                         var, var_indexers, method, **kwargs
   2458                     )
   2459                 elif all(d not in indexers for d in var.dims):

~/dev/xarray/xarray/core/missing.py in interp(var, indexes_coords, method, **kwargs)
    533         else:
    534             out_dims.add(d)
--> 535     return result.transpose(*tuple(out_dims))
    536
    537

~/dev/xarray/xarray/core/variable.py in transpose(self, *dims)
   1219             return self.copy(deep=False)
   1220
-> 1221         data = as_indexable(self._data).transpose(axes)
   1222         return type(self)(dims, data, self._attrs, self._encoding, fastpath=True)
   1223

~/dev/xarray/xarray/core/indexing.py in transpose(self, order)
   1218
   1219     def transpose(self, order):
-> 1220         return self.array.transpose(order)
   1221
   1222     def __getitem__(self, key):

ValueError: axes don't match array

In [44]: data.reindex(y=ind)
/Users/shoyer/dev/xarray/xarray/core/dataarray.py:1240: FutureWarning: Indexer has dimensions ('x', 'z') that are different from that to be indexed along y. This will behave differently in the future.
  fill_value=fill_value,
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-44-1277ead996ae> in <module>
----> 1 data.reindex(y=ind)

~/dev/xarray/xarray/core/dataarray.py in reindex(self, indexers, method, tolerance, copy, fill_value, **indexers_kwargs)
   1238             tolerance=tolerance,
   1239             copy=copy,
-> 1240             fill_value=fill_value,
   1241         )
   1242         return self._from_temp_dataset(ds)

~/dev/xarray/xarray/core/dataset.py in reindex(self, indexers, method, tolerance, copy, fill_value, **indexers_kwargs)
   2360             tolerance,
   2361             copy=copy,
-> 2362             fill_value=fill_value,
   2363         )
   2364         coord_names = set(self._coord_names)

~/dev/xarray/xarray/core/alignment.py in reindex_variables(variables, sizes, indexes, indexers, method, tolerance, copy, fill_value)
    398             )
    399
--> 400         target = new_indexes[dim] = utils.safe_cast_to_index(indexers[dim])
    401
    402         if dim in indexes:

~/dev/xarray/xarray/core/utils.py in safe_cast_to_index(array)
    104         index = array
    105     elif hasattr(array, "to_index"):
--> 106         index = array.to_index()
    107     else:
    108         kwargs = {}

~/dev/xarray/xarray/core/dataarray.py in to_index(self)
    545         arrays.
    546         """
--> 547         return self.variable.to_index()
    548
    549     @property

~/dev/xarray/xarray/core/variable.py in to_index(self)
    445     def to_index(self):
    446         """Convert this variable to a pandas.Index"""
--> 447         return self.to_index_variable().to_index()
    448
    449     def to_dict(self, data=True):

~/dev/xarray/xarray/core/variable.py in to_index_variable(self)
    438         """Return this variable as an xarray.IndexVariable"""
    439         return IndexVariable(
--> 440             self.dims, self._data, self._attrs, encoding=self._encoding, fastpath=True
    441         )
    442

~/dev/xarray/xarray/core/variable.py in __init__(self, dims, data, attrs, encoding, fastpath)
   1941         super().__init__(dims, data, attrs, encoding, fastpath)
   1942         if self.ndim != 1:
-> 1943             raise ValueError("%s objects must be 1-dimensional" % type(self).__name__)
   1944
   1945         # Unlike in Variable, always eagerly load values into memory

ValueError: IndexVariable objects must be 1-dimensional

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions