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 (