Skip to content

Commit 2031b52

Browse files
committed
Merge branch 'master' into pint-support-dataarray
2 parents 46ab60d + ba9f822 commit 2031b52

19 files changed

+349
-59
lines changed

azure-pipelines.yml

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ jobs:
2020
conda_env: py37
2121
py38:
2222
conda_env: py38
23+
py38-all-but-dask:
24+
conda_env: py38-all-but-dask
2325
py38-upstream-dev:
2426
conda_env: py38
2527
upstream_dev: true
@@ -32,16 +34,15 @@ jobs:
3234
steps:
3335
- template: ci/azure/unit-tests.yml
3436

35-
# excluded while waiting for https://github.com/conda-forge/libwebp-feedstock/issues/26
36-
# - job: MacOSX
37-
# strategy:
38-
# matrix:
39-
# py38:
40-
# conda_env: py38
41-
# pool:
42-
# vmImage: 'macOS-10.15'
43-
# steps:
44-
# - template: ci/azure/unit-tests.yml
37+
- job: MacOSX
38+
strategy:
39+
matrix:
40+
py38:
41+
conda_env: py38
42+
pool:
43+
vmImage: 'macOS-10.15'
44+
steps:
45+
- template: ci/azure/unit-tests.yml
4546

4647
- job: Windows
4748
strategy:

ci/requirements/py38-all-but-dask.yml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
name: xarray-tests
2+
channels:
3+
- conda-forge
4+
dependencies:
5+
- python=3.8
6+
- black
7+
- boto3
8+
- bottleneck
9+
- cartopy
10+
- cdms2
11+
- cfgrib
12+
- cftime
13+
- coveralls
14+
- flake8
15+
- h5netcdf
16+
- h5py
17+
- hdf5
18+
- hypothesis
19+
- isort
20+
- lxml # Optional dep of pydap
21+
- matplotlib
22+
- mypy=0.761 # Must match .pre-commit-config.yaml
23+
- nc-time-axis
24+
- netcdf4
25+
- numba
26+
- numpy
27+
- pandas
28+
- pint
29+
- pip
30+
- pseudonetcdf
31+
- pydap
32+
- pynio
33+
- pytest
34+
- pytest-cov
35+
- pytest-env
36+
- rasterio
37+
- scipy
38+
- seaborn
39+
- setuptools
40+
- sparse
41+
- toolz
42+
- zarr
43+
- pip:
44+
- numbagg

doc/groupby.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ This last line is roughly equivalent to the following::
157157

158158
results = []
159159
for label, group in ds.groupby('letters'):
160-
results.append(group - alt.sel(x=label))
160+
results.append(group - alt.sel(letters=label))
161161
xr.concat(results, dim='x')
162162

163163
Squeezing

doc/whats-new.rst

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ New Features
3535
:py:func:`combine_by_coords` and :py:func:`combine_nested` using
3636
combine_attrs keyword argument. (:issue:`3865`, :pull:`3877`)
3737
By `John Omotani <https://github.com/johnomotani>`_
38+
- 'missing_dims' argument to :py:meth:`Dataset.isel`,
39+
`:py:meth:`DataArray.isel` and :py:meth:`Variable.isel` to allow replacing
40+
the exception when a dimension passed to ``isel`` is not present with a
41+
warning, or just ignore the dimension. (:issue:`3866`, :pull:`3923`)
42+
By `John Omotani <https://github.com/johnomotani>`_
3843
- Limited the length of array items with long string reprs to a
3944
reasonable width (:pull:`3900`)
4045
By `Maximilian Roos <https://github.com/max-sixty>`_
@@ -43,14 +48,24 @@ New Features
4348
By `Todd Jennings <https://github.com/toddrjen>`_
4449
- More support for unit aware arrays with pint (:pull:`3643`)
4550
By `Justus Magin <https://github.com/keewis>`_.
46-
51+
- Allow plotting of boolean arrays. (:pull:`3766`)
52+
By `Marek Jacob <https://github.com/MeraX>`_
4753

4854
Bug fixes
4955
~~~~~~~~~
56+
- Fix renaming of coords when one or more stacked coords is not in
57+
sorted order during stack+groupby+apply operations. (:issue:`3287`,
58+
:pull:`3906`) By `Spencer Hill <https://github.com/spencerahill>`_
5059
- Fix a regression where deleting a coordinate from a copied :py:class:`DataArray`
5160
can affect the original :py:class:`Dataarray`. (:issue:`3899`, :pull:`3871`)
5261
By `Todd Jennings <https://github.com/toddrjen>`_
53-
62+
- Use divergent colormap if ``levels`` spans 0. (:issue:`3524`)
63+
By `Deepak Cherian <https://github.com/dcherian>`_
64+
- Fix ``FacetGrid`` when ``vmin == vmax``. (:issue:`3734`)
65+
By `Deepak Cherian <https://github.com/dcherian>`_
66+
- Fix bug where plotting line plots with 2D coordinates depended on dimension
67+
order. (:issue:`3933`)
68+
By `Tom Nicholas <https://github.com/TomNicholas>`_.
5469

5570
Documentation
5671
~~~~~~~~~~~~~
@@ -65,6 +80,9 @@ Internal Changes
6580
- Run the ``isort`` pre-commit hook only on python source files
6681
and update the ``flake8`` version. (:issue:`3750`, :pull:`3711`)
6782
By `Justus Magin <https://github.com/keewis>`_.
83+
- Add a CI job that runs the tests with every optional dependency
84+
except ``dask``. (:issue:`3794`, :pull:`3919`)
85+
By `Justus Magin <https://github.com/keewis>`_.
6886

6987

7088
.. _whats-new.0.15.1:
@@ -98,13 +116,13 @@ New Features
98116
- Added support for :py:class:`pandas.DatetimeIndex`-style rounding of
99117
``cftime.datetime`` objects directly via a :py:class:`CFTimeIndex` or via the
100118
:py:class:`~core.accessor_dt.DatetimeAccessor`.
101-
By `Spencer Clark <https://github.com/spencerkclark>`_
119+
By `Spencer Clark <https://github.com/spencerkclark>`_
102120
- Support new h5netcdf backend keyword `phony_dims` (available from h5netcdf
103121
v0.8.0 for :py:class:`~xarray.backends.H5NetCDFStore`.
104122
By `Kai Mühlbauer <https://github.com/kmuehlbauer>`_.
105123
- Add partial support for unit aware arrays with pint. (:pull:`3706`, :pull:`3611`)
106124
By `Justus Magin <https://github.com/keewis>`_.
107-
- :py:meth:`Dataset.groupby` and :py:meth:`DataArray.groupby` now raise a
125+
- :py:meth:`Dataset.groupby` and :py:meth:`DataArray.groupby` now raise a
108126
`TypeError` on multiple string arguments. Receiving multiple string arguments
109127
often means a user is attempting to pass multiple dimensions as separate
110128
arguments and should instead pass a single list of dimensions.
@@ -122,7 +140,7 @@ New Features
122140
By `Maximilian Roos <https://github.com/max-sixty>`_.
123141
- ``skipna`` is available in :py:meth:`Dataset.quantile`, :py:meth:`DataArray.quantile`,
124142
:py:meth:`core.groupby.DatasetGroupBy.quantile`, :py:meth:`core.groupby.DataArrayGroupBy.quantile`
125-
(:issue:`3843`, :pull:`3844`)
143+
(:issue:`3843`, :pull:`3844`)
126144
By `Aaron Spring <https://github.com/aaronspring>`_.
127145

128146
Bug fixes
@@ -816,7 +834,7 @@ Bug fixes
816834
Documentation
817835
~~~~~~~~~~~~~
818836

819-
- Created a `PR checklist <https://xarray.pydata.org/en/stable/contributing.html/contributing.html#pr-checklist>`_
837+
- Created a `PR checklist <https://xarray.pydata.org/en/stable/contributing.html/contributing.html#pr-checklist>`_
820838
as a quick reference for tasks before creating a new PR
821839
or pushing new commits.
822840
By `Gregory Gundersen <https://github.com/gwgundersen>`_.

xarray/backends/zarr.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ def __getitem__(self, key):
5656
return array[key.tuple]
5757
elif isinstance(key, indexing.VectorizedIndexer):
5858
return array.vindex[
59-
indexing._arrayize_vectorized_indexer(key.tuple, self.shape).tuple
59+
indexing._arrayize_vectorized_indexer(key, self.shape).tuple
6060
]
6161
else:
6262
assert isinstance(key, indexing.OuterIndexer)
@@ -586,6 +586,12 @@ def open_zarr(
586586
"Instead found %s. " % chunks
587587
)
588588

589+
if chunks == "auto":
590+
try:
591+
import dask.array # noqa
592+
except ImportError:
593+
chunks = None
594+
589595
if not decode_cf:
590596
mask_and_scale = False
591597
decode_times = False

xarray/core/dataarray.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,25 +1007,51 @@ def isel(
10071007
self,
10081008
indexers: Mapping[Hashable, Any] = None,
10091009
drop: bool = False,
1010+
missing_dims: str = "raise",
10101011
**indexers_kwargs: Any,
10111012
) -> "DataArray":
10121013
"""Return a new DataArray whose data is given by integer indexing
10131014
along the specified dimension(s).
10141015
1016+
Parameters
1017+
----------
1018+
indexers : dict, optional
1019+
A dict with keys matching dimensions and values given
1020+
by integers, slice objects or arrays.
1021+
indexer can be a integer, slice, array-like or DataArray.
1022+
If DataArrays are passed as indexers, xarray-style indexing will be
1023+
carried out. See :ref:`indexing` for the details.
1024+
One of indexers or indexers_kwargs must be provided.
1025+
drop : bool, optional
1026+
If ``drop=True``, drop coordinates variables indexed by integers
1027+
instead of making them scalar.
1028+
missing_dims : {"raise", "warn", "ignore"}, default "raise"
1029+
What to do if dimensions that should be selected from are not present in the
1030+
DataArray:
1031+
- "exception": raise an exception
1032+
- "warning": raise a warning, and ignore the missing dimensions
1033+
- "ignore": ignore the missing dimensions
1034+
**indexers_kwargs : {dim: indexer, ...}, optional
1035+
The keyword arguments form of ``indexers``.
1036+
10151037
See Also
10161038
--------
10171039
Dataset.isel
10181040
DataArray.sel
10191041
"""
1042+
10201043
indexers = either_dict_or_kwargs(indexers, indexers_kwargs, "isel")
1044+
10211045
if any(is_fancy_indexer(idx) for idx in indexers.values()):
1022-
ds = self._to_temp_dataset()._isel_fancy(indexers, drop=drop)
1046+
ds = self._to_temp_dataset()._isel_fancy(
1047+
indexers, drop=drop, missing_dims=missing_dims
1048+
)
10231049
return self._from_temp_dataset(ds)
10241050

10251051
# Much faster algorithm for when all indexers are ints, slices, one-dimensional
10261052
# lists, or zero or one-dimensional np.ndarray's
10271053

1028-
variable = self._variable.isel(indexers)
1054+
variable = self._variable.isel(indexers, missing_dims=missing_dims)
10291055

10301056
coords = {}
10311057
for coord_name, coord_value in self._coords.items():

xarray/core/dataset.py

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
_check_inplace,
8888
_default,
8989
decode_numpy_dict_values,
90+
drop_dims_from_indexers,
9091
either_dict_or_kwargs,
9192
hashable,
9293
infix_dims,
@@ -1767,7 +1768,7 @@ def maybe_chunk(name, var, chunks):
17671768
return self._replace(variables)
17681769

17691770
def _validate_indexers(
1770-
self, indexers: Mapping[Hashable, Any]
1771+
self, indexers: Mapping[Hashable, Any], missing_dims: str = "raise",
17711772
) -> Iterator[Tuple[Hashable, Union[int, slice, np.ndarray, Variable]]]:
17721773
""" Here we make sure
17731774
+ indexer has a valid keys
@@ -1777,9 +1778,7 @@ def _validate_indexers(
17771778
"""
17781779
from .dataarray import DataArray
17791780

1780-
invalid = indexers.keys() - self.dims.keys()
1781-
if invalid:
1782-
raise ValueError("dimensions %r do not exist" % invalid)
1781+
indexers = drop_dims_from_indexers(indexers, self.dims, missing_dims)
17831782

17841783
# all indexers should be int, slice, np.ndarrays, or Variable
17851784
for k, v in indexers.items():
@@ -1875,6 +1874,7 @@ def isel(
18751874
self,
18761875
indexers: Mapping[Hashable, Any] = None,
18771876
drop: bool = False,
1877+
missing_dims: str = "raise",
18781878
**indexers_kwargs: Any,
18791879
) -> "Dataset":
18801880
"""Returns a new dataset with each array indexed along the specified
@@ -1896,6 +1896,12 @@ def isel(
18961896
drop : bool, optional
18971897
If ``drop=True``, drop coordinates variables indexed by integers
18981898
instead of making them scalar.
1899+
missing_dims : {"raise", "warn", "ignore"}, default "raise"
1900+
What to do if dimensions that should be selected from are not present in the
1901+
Dataset:
1902+
- "exception": raise an exception
1903+
- "warning": raise a warning, and ignore the missing dimensions
1904+
- "ignore": ignore the missing dimensions
18991905
**indexers_kwargs : {dim: indexer, ...}, optional
19001906
The keyword arguments form of ``indexers``.
19011907
One of indexers or indexers_kwargs must be provided.
@@ -1918,13 +1924,11 @@ def isel(
19181924
"""
19191925
indexers = either_dict_or_kwargs(indexers, indexers_kwargs, "isel")
19201926
if any(is_fancy_indexer(idx) for idx in indexers.values()):
1921-
return self._isel_fancy(indexers, drop=drop)
1927+
return self._isel_fancy(indexers, drop=drop, missing_dims=missing_dims)
19221928

19231929
# Much faster algorithm for when all indexers are ints, slices, one-dimensional
19241930
# lists, or zero or one-dimensional np.ndarray's
1925-
invalid = indexers.keys() - self.dims.keys()
1926-
if invalid:
1927-
raise ValueError("dimensions %r do not exist" % invalid)
1931+
indexers = drop_dims_from_indexers(indexers, self.dims, missing_dims)
19281932

19291933
variables = {}
19301934
dims: Dict[Hashable, Tuple[int, ...]] = {}
@@ -1958,10 +1962,16 @@ def isel(
19581962
file_obj=self._file_obj,
19591963
)
19601964

1961-
def _isel_fancy(self, indexers: Mapping[Hashable, Any], *, drop: bool) -> "Dataset":
1965+
def _isel_fancy(
1966+
self,
1967+
indexers: Mapping[Hashable, Any],
1968+
*,
1969+
drop: bool,
1970+
missing_dims: str = "raise",
1971+
) -> "Dataset":
19621972
# Note: we need to preserve the original indexers variable in order to merge the
19631973
# coords below
1964-
indexers_list = list(self._validate_indexers(indexers))
1974+
indexers_list = list(self._validate_indexers(indexers, missing_dims))
19651975

19661976
variables: Dict[Hashable, Variable] = {}
19671977
indexes: Dict[Hashable, pd.Index] = {}

xarray/core/groupby.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,8 +370,10 @@ def __init__(
370370
group = group.dropna(group_dim)
371371

372372
# look through group to find the unique values
373+
group_as_index = safe_cast_to_index(group)
374+
sort = bins is None and (not isinstance(group_as_index, pd.MultiIndex))
373375
unique_values, group_indices = unique_value_groups(
374-
safe_cast_to_index(group), sort=(bins is None)
376+
group_as_index, sort=sort
375377
)
376378
unique_coord = IndexVariable(group.name, unique_values)
377379

0 commit comments

Comments
 (0)