diff --git a/ci/azure/install.yml b/ci/azure/install.yml index fee886ba804..baa69bcc8d5 100644 --- a/ci/azure/install.yml +++ b/ci/azure/install.yml @@ -16,9 +16,9 @@ steps: --pre \ --upgrade \ matplotlib \ + numpy \ pandas \ scipy - # numpy \ # FIXME https://github.com/pydata/xarray/issues/3409 pip install \ --no-deps \ --upgrade \ diff --git a/doc/whats-new.rst b/doc/whats-new.rst index abd94779435..c10d49537dd 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -100,6 +100,12 @@ Bug fixes (:issue:`3402`). By `Deepak Cherian `_ - Allow appending datetime and bool data variables to zarr stores. (:issue:`3480`). By `Akihiro Matsukawa `_. +- Add support for numpy >=1.18 (:issue:`3409`). + By `Guido Imperiale `_. +- Add support for pandas >=0.26 (:issue:`3440`). + By `Deepak Cherian `_. +- Add support for pseudonetcdf >=3.1 (:pull:`3485`). + By `Barron Henderson `_. Documentation ~~~~~~~~~~~~~ @@ -118,7 +124,6 @@ Documentation Internal Changes ~~~~~~~~~~~~~~~~ - - Added integration tests against `pint `_. (:pull:`3238`, :pull:`3447`, :pull:`3493`, :pull:`3508`) by `Justus Magin `_. diff --git a/xarray/core/duck_array_ops.py b/xarray/core/duck_array_ops.py index 71e79335c3d..144a00bf072 100644 --- a/xarray/core/duck_array_ops.py +++ b/xarray/core/duck_array_ops.py @@ -10,6 +10,7 @@ import numpy as np import pandas as pd +from distutils.version import LooseVersion from . import dask_array_ops, dtypes, npcompat, nputils from .nputils import nanfirst, nanlast @@ -351,6 +352,32 @@ def f(values, axis=None, skipna=None, **kwargs): _mean = _create_nan_agg_method("mean") +def _datetime_crude_nanmin(array): + """Implement nanmin for datetime64 arrays, with caveats: + + - can't accept an axis parameter + - will return incorrect results if the array exclusively contains NaT + """ + if LooseVersion(np.__version__) < "1.18": + # numpy.min < 1.18 incorrectly skips NaT - which we exploit here + return min(array, skipna=False) + # This requires numpy >= 1.15 + + from .dataarray import DataArray + from .variable import Variable + + if isinstance(array, (DataArray, Variable)): + array = array.data + array = array.ravel() + array = array[~pandas_isnull(array)] + + assert array.dtype.kind in "Mm" + assert array.dtype.itemsize == 8 + initial = np.array(2 ** 63 - 1, dtype=array.dtype) + + return min(array, initial=initial, skipna=False) + + def datetime_to_numeric(array, offset=None, datetime_unit=None, dtype=float): """Convert an array containing datetime-like data to an array of floats. @@ -370,7 +397,10 @@ def datetime_to_numeric(array, offset=None, datetime_unit=None, dtype=float): """ # TODO: make this function dask-compatible? if offset is None: - offset = array.min() + if array.dtype.kind in "Mm": + offset = _datetime_crude_nanmin(array) + else: + offset = min(array) array = array - offset if not hasattr(array, "dtype"): # scalar is converted to 0d-array @@ -401,7 +431,8 @@ def mean(array, axis=None, skipna=None, **kwargs): array = asarray(array) if array.dtype.kind in "Mm": - offset = min(array) + offset = _datetime_crude_nanmin(array) + # xarray always uses np.datetime64[ns] for np.datetime64 data dtype = "timedelta64[ns]" return (