Description
MCVE Code Sample
In [1]: import xarray as xr
In [2]: times = xr.cftime_range('0001', periods=3, freq='500Y')
In [3]: da = xr.DataArray(range(3), dims=['time'], coords=[times])
In [4]: da.interp(time=['0002-05-01'])
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-4-f781cb4d500e> in <module>
----> 1 da.interp(time=['0002-05-01'])
~/Software/miniconda3/envs/xarray-tests/lib/python3.7/site-packages/xarray/core/dataarray.py in interp(self, coords, method, assume_sorted, kwargs, **coords_kwargs)
1353 kwargs=kwargs,
1354 assume_sorted=assume_sorted,
-> 1355 **coords_kwargs,
1356 )
1357 return self._from_temp_dataset(ds)
~/Software/miniconda3/envs/xarray-tests/lib/python3.7/site-packages/xarray/core/dataset.py in interp(self, coords, method, assume_sorted, kwargs, **coords_kwargs)
2565 if k in var.dims
2566 }
-> 2567 variables[name] = missing.interp(var, var_indexers, method, **kwargs)
2568 elif all(d not in indexers for d in var.dims):
2569 # keep unrelated object array
~/Software/miniconda3/envs/xarray-tests/lib/python3.7/site-packages/xarray/core/missing.py in interp(var, indexes_coords, method, **kwargs)
607 new_dims = broadcast_dims + list(destination[0].dims)
608 interped = interp_func(
--> 609 var.transpose(*original_dims).data, x, destination, method, kwargs
610 )
611
~/Software/miniconda3/envs/xarray-tests/lib/python3.7/site-packages/xarray/core/missing.py in interp_func(var, x, new_x, method, kwargs)
683 )
684
--> 685 return _interpnd(var, x, new_x, func, kwargs)
686
687
~/Software/miniconda3/envs/xarray-tests/lib/python3.7/site-packages/xarray/core/missing.py in _interpnd(var, x, new_x, func, kwargs)
698
699 def _interpnd(var, x, new_x, func, kwargs):
--> 700 x, new_x = _floatize_x(x, new_x)
701
702 if len(x) == 1:
~/Software/miniconda3/envs/xarray-tests/lib/python3.7/site-packages/xarray/core/missing.py in _floatize_x(x, new_x)
556 # represented by float.
557 xmin = x[i].values.min()
--> 558 x[i] = x[i]._to_numeric(offset=xmin, dtype=np.float64)
559 new_x[i] = new_x[i]._to_numeric(offset=xmin, dtype=np.float64)
560 return x, new_x
~/Software/miniconda3/envs/xarray-tests/lib/python3.7/site-packages/xarray/core/variable.py in _to_numeric(self, offset, datetime_unit, dtype)
2001 """
2002 numeric_array = duck_array_ops.datetime_to_numeric(
-> 2003 self.data, offset, datetime_unit, dtype
2004 )
2005 return type(self)(self.dims, numeric_array, self._attrs)
~/Software/miniconda3/envs/xarray-tests/lib/python3.7/site-packages/xarray/core/duck_array_ops.py in datetime_to_numeric(array, offset, datetime_unit, dtype)
410 if array.dtype.kind in "mM":
411 return np.where(isnull(array), np.nan, array.astype(dtype))
--> 412 return array.astype(dtype)
413
414
TypeError: float() argument must be a string or a number, not 'datetime.timedelta'
Problem Description
In principle we should be able to get this to work. The issue stems from the following logic in datetime_to_numeric
:
xarray/xarray/core/duck_array_ops.py
Lines 402 to 404 in 45fd0e6
Here we are relying on pandas to convert an array of
datetime.timedelta
objects to an array with dtype timedelta64[ns]
. If the array of datetime.timedelta
objects cannot be safely converted to timedelta64[ns]
(e.g. due to an integer overflow) then this line is silently a no-op which leads to the error downstream at the dtype conversion step. This is my fault originally for suggesting this approach, #2668 (comment).
To solve this I think we'll need to write our own logic to convert (as @huard notes we should be able to use NumPy directly here for the conversion). We should not consider ourselves beholden to using nanosecond resolution for a couple of reasons:datetime.timedelta
objects to numeric values instead of relying on pandas/NumPy.
datetime.timedelta
objects do not natively support nanosecond resolution; they have microsecond resolution natively, which corresponds with a NumPy timedelta range of +/- 2.9e5 years.- One motivation/use-case for cftime dates is that they can represent long time periods that cannot be represented using a standard
DatetimeIndex
. We should do everything we can to support this with aCFTimeIndex
.
@huard @dcherian this is an important issue we'll need to solve to be able to use a fixed offset for cftime dates for an application like polyfit
/polyval
.
Output of xr.show_versions()
INSTALLED VERSIONS
commit: None
python: 3.7.3 | packaged by conda-forge | (default, Jul 1 2019, 14:38:56)
[Clang 4.0.1 (tags/RELEASE_401/final)]
python-bits: 64
OS: Darwin
OS-release: 19.0.0
machine: x86_64
processor: i386
byteorder: little
LC_ALL: None
LANG: en_US.UTF-8
LOCALE: en_US.UTF-8
libhdf5: 1.10.5
libnetcdf: None
xarray: 0.14.1
pandas: 0.25.0
numpy: 1.17.0
scipy: 1.3.1
netCDF4: None
pydap: installed
h5netcdf: 0.7.4
h5py: 2.9.0
Nio: None
zarr: 2.3.2
cftime: 1.0.4.2
nc_time_axis: None
PseudoNetCDF: None
rasterio: 1.0.25
cfgrib: 0.9.7.1
iris: None
bottleneck: 1.2.1
dask: 2.9.0+2.gd0daa5bc
distributed: 2.9.0
matplotlib: 3.1.1
cartopy: None
seaborn: 0.9.0
numbagg: installed
setuptools: 42.0.2.post20191201
pip: 19.2.2
conda: None
pytest: 5.0.1
IPython: 7.10.1
sphinx: None