From 0f74942cba9cb31259fb84e2ea6fdde044797e7b Mon Sep 17 00:00:00 2001 From: keisukefujii Date: Wed, 8 Jan 2020 19:44:07 +0900 Subject: [PATCH 01/11] Added a support with categorical index --- doc/whats-new.rst | 2 ++ xarray/core/indexing.py | 4 ++++ xarray/tests/test_dataset.py | 8 ++++++++ 3 files changed, 14 insertions(+) diff --git a/doc/whats-new.rst b/doc/whats-new.rst index 70853dbb730..b925fe2836d 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -25,6 +25,8 @@ Breaking changes New Features ~~~~~~~~~~~~ +- Now :py:func:`sel` works dataarray / dataset with pd.CategoricalIndex. (:issue:`3669`) + By `Keisuke Fujii `_. - Implement :py:func:`median` and :py:func:`nanmedian` for dask arrays. This works by rechunking to a single chunk along all reduction axes. (:issue:`2999`). By `Deepak Cherian `_. diff --git a/xarray/core/indexing.py b/xarray/core/indexing.py index 8e851b39c3e..e1e073f3060 100644 --- a/xarray/core/indexing.py +++ b/xarray/core/indexing.py @@ -175,6 +175,10 @@ def convert_label_indexer(index, label, index_name="", method=None, tolerance=No if label.ndim == 0: if isinstance(index, pd.MultiIndex): indexer, new_index = index.get_loc_level(label.item(), level=0) + elif isinstance(index, pd.CategoricalIndex): + if tolerance is not None: + raise ValueError("tolerance is not valid with categorical index.") + indexer = index.get_loc(label.item()) else: indexer = index.get_loc( label.item(), method=method, tolerance=tolerance diff --git a/xarray/tests/test_dataset.py b/xarray/tests/test_dataset.py index edda4cb2a58..674dce0e8ad 100644 --- a/xarray/tests/test_dataset.py +++ b/xarray/tests/test_dataset.py @@ -1392,6 +1392,14 @@ def test_sel_dataarray_mindex(self): ) ) + def test_sel_categorical(self): + ind = pd.Series(["foo", "bar"], dtype="category") + df = pd.DataFrame({"ind": ind, "values": [1, 2]}) + ds = df.set_index("ind").to_xarray() + actual = ds.sel(ind="bar") + expected = ds.isel(ind=1) + assert_identical(expected, actual) + def test_sel_drop(self): data = Dataset({"foo": ("x", [1, 2, 3])}, {"x": [0, 1, 2]}) expected = Dataset({"foo": 1}) From 0e0db2f5459654faa2ccd9b78181eac5aa9e084a Mon Sep 17 00:00:00 2001 From: keisukefujii Date: Thu, 9 Jan 2020 21:08:01 +0900 Subject: [PATCH 02/11] fix from_dataframe --- xarray/core/dataset.py | 20 ++++++++++++-------- xarray/core/indexes.py | 17 +++++++++++++++++ xarray/tests/test_dataset.py | 14 ++++++++++++++ 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/xarray/core/dataset.py b/xarray/core/dataset.py index 032c66d3778..4309bfe53a7 100644 --- a/xarray/core/dataset.py +++ b/xarray/core/dataset.py @@ -41,6 +41,7 @@ formatting, formatting_html, groupby, + indexes, ops, resample, rolling, @@ -4454,7 +4455,7 @@ def to_dataframe(self): return self._to_dataframe(self.dims) def _set_sparse_data_from_dataframe( - self, dataframe: pd.DataFrame, dims: tuple, shape: Tuple[int, ...] + self, dataframe: pd.DataFrame, dims: tuple ) -> None: from sparse import COO @@ -4467,9 +4468,11 @@ def _set_sparse_data_from_dataframe( codes = idx.labels coords = np.stack([np.asarray(code) for code in codes], axis=0) is_sorted = idx.is_lexsorted + shape = tuple(lev.size for lev in idx.levels) else: coords = np.arange(idx.size).reshape(1, -1) is_sorted = True + shape = (idx.size,) for name, series in dataframe.items(): # Cast to a NumPy array first, in case the Series is a pandas @@ -4494,14 +4497,16 @@ def _set_sparse_data_from_dataframe( self[name] = (dims, data) def _set_numpy_data_from_dataframe( - self, dataframe: pd.DataFrame, dims: tuple, shape: Tuple[int, ...] + self, dataframe: pd.DataFrame, dims: tuple ) -> None: idx = dataframe.index if isinstance(idx, pd.MultiIndex): # expand the DataFrame to include the product of all levels full_idx = pd.MultiIndex.from_product(idx.levels, names=idx.names) dataframe = dataframe.reindex(full_idx) - + shape = tuple(lev.size for lev in idx.levels) + else: + shape = (idx.size,) for name, series in dataframe.items(): data = np.asarray(series).reshape(shape) self[name] = (dims, data) @@ -4542,7 +4547,8 @@ def from_dataframe(cls, dataframe: pd.DataFrame, sparse: bool = False) -> "Datas if not dataframe.columns.is_unique: raise ValueError("cannot convert DataFrame with non-unique columns") - idx = dataframe.index + idx = indexes.remove_unused(dataframe.index) + dataframe = dataframe.set_index(idx) obj = cls() if isinstance(idx, pd.MultiIndex): @@ -4552,17 +4558,15 @@ def from_dataframe(cls, dataframe: pd.DataFrame, sparse: bool = False) -> "Datas ) for dim, lev in zip(dims, idx.levels): obj[dim] = (dim, lev) - shape = tuple(lev.size for lev in idx.levels) else: index_name = idx.name if idx.name is not None else "index" dims = (index_name,) obj[index_name] = (dims, idx) - shape = (idx.size,) if sparse: - obj._set_sparse_data_from_dataframe(dataframe, dims, shape) + obj._set_sparse_data_from_dataframe(dataframe, dims) else: - obj._set_numpy_data_from_dataframe(dataframe, dims, shape) + obj._set_numpy_data_from_dataframe(dataframe, dims) return obj def to_dask_dataframe(self, dim_order=None, set_index=False): diff --git a/xarray/core/indexes.py b/xarray/core/indexes.py index 8337a0f082a..ba675c0d3b4 100644 --- a/xarray/core/indexes.py +++ b/xarray/core/indexes.py @@ -9,6 +9,23 @@ from .variable import Variable +def remove_unused(index): + """ Remove unused levels if CategoricalIndex """ + if isinstance(index, pd.MultiIndex): + # if it contains CategoricalIndex, we need to remove unused categories + # manually. See https://github.com/pandas-dev/pandas/issues/30846 + if any(isinstance(lev, pd.CategoricalIndex) for lev in index.levels): + levels = [] + for i, level in enumerate(index.levels): + if isinstance(level, pd.CategoricalIndex): + level = level[index.codes[i]].remove_unused_categories() + levels.append(level) + index = pd.MultiIndex.from_arrays(levels, names=index.names) + if isinstance(index, pd.CategoricalIndex): + index = index.remove_unused_categories() + return index + + class Indexes(collections.abc.Mapping): """Immutable proxy for Dataset or DataArrary indexes.""" diff --git a/xarray/tests/test_dataset.py b/xarray/tests/test_dataset.py index 674dce0e8ad..edec54477e4 100644 --- a/xarray/tests/test_dataset.py +++ b/xarray/tests/test_dataset.py @@ -3844,6 +3844,20 @@ def test_to_and_from_dataframe(self): expected = pd.DataFrame([[]], index=idx) assert expected.equals(actual), (expected, actual) + def test_from_dataframe_categorical(self): + cat = pd.CategoricalDtype(categories=["foo", "bar", "baz"]) + i1 = pd.Series(["foo", "bar"], dtype=cat) + i2 = pd.Series(["bar", "bar"], dtype=cat) + + df = pd.DataFrame({"i1": i1, "i2": i2, "values": [1, 2]}) + ds = df.set_index("i1").to_xarray() + assert len(ds["i1"]) == 2 + + ds = df.set_index(["i1", "i2"]).to_xarray() + print(ds) + assert len(ds["i1"]) == 2 + assert len(ds["i2"]) == 1 + @requires_sparse def test_from_dataframe_sparse(self): import sparse From cd6f3c8fbdf501ab5b834c82aa1c3f0eb0c17d72 Mon Sep 17 00:00:00 2001 From: keisukefujii Date: Fri, 10 Jan 2020 15:58:40 +0900 Subject: [PATCH 03/11] update a test --- xarray/tests/test_dataset.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/xarray/tests/test_dataset.py b/xarray/tests/test_dataset.py index edec54477e4..599d7b12f80 100644 --- a/xarray/tests/test_dataset.py +++ b/xarray/tests/test_dataset.py @@ -3845,18 +3845,20 @@ def test_to_and_from_dataframe(self): assert expected.equals(actual), (expected, actual) def test_from_dataframe_categorical(self): - cat = pd.CategoricalDtype(categories=["foo", "bar", "baz"]) - i1 = pd.Series(["foo", "bar"], dtype=cat) - i2 = pd.Series(["bar", "bar"], dtype=cat) + cat = pd.CategoricalDtype( + categories=["foo", "bar", "baz", + "qux", "quux", "corge"]) + i1 = pd.Series(["foo", "bar", "foo"], dtype=cat) + i2 = pd.Series(["bar", "bar", "baz"], dtype=cat) - df = pd.DataFrame({"i1": i1, "i2": i2, "values": [1, 2]}) + df = pd.DataFrame({"i1": i1, "i2": i2, "values": [1, 2, 3]}) ds = df.set_index("i1").to_xarray() - assert len(ds["i1"]) == 2 + assert len(ds["i1"]) == 3 ds = df.set_index(["i1", "i2"]).to_xarray() print(ds) assert len(ds["i1"]) == 2 - assert len(ds["i2"]) == 1 + assert len(ds["i2"]) == 2 @requires_sparse def test_from_dataframe_sparse(self): From 98d38b09f45ba2a5df6b6b19705eaf478b5a96ef Mon Sep 17 00:00:00 2001 From: keisukefujii Date: Sat, 11 Jan 2020 11:21:45 +0900 Subject: [PATCH 04/11] Added more tests --- xarray/core/dataset.py | 6 +++--- xarray/core/indexes.py | 1 + xarray/tests/test_dataset.py | 20 ++++++++++++++++++++ 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/xarray/core/dataset.py b/xarray/core/dataset.py index 4309bfe53a7..23e9c4564ca 100644 --- a/xarray/core/dataset.py +++ b/xarray/core/dataset.py @@ -41,7 +41,6 @@ formatting, formatting_html, groupby, - indexes, ops, resample, rolling, @@ -65,6 +64,7 @@ default_indexes, isel_variable_and_index, propagate_indexes, + remove_unused, roll_index, ) from .indexing import is_fancy_indexer @@ -3407,7 +3407,7 @@ def ensure_stackable(val): def _unstack_once(self, dim: Hashable, fill_value, sparse) -> "Dataset": index = self.get_index(dim) - index = index.remove_unused_levels() + index = remove_unused(index) full_idx = pd.MultiIndex.from_product(index.levels, names=index.names) # take a shortcut in case the MultiIndex was not modified. @@ -4547,7 +4547,7 @@ def from_dataframe(cls, dataframe: pd.DataFrame, sparse: bool = False) -> "Datas if not dataframe.columns.is_unique: raise ValueError("cannot convert DataFrame with non-unique columns") - idx = indexes.remove_unused(dataframe.index) + idx = remove_unused(dataframe.index) dataframe = dataframe.set_index(idx) obj = cls() diff --git a/xarray/core/indexes.py b/xarray/core/indexes.py index ba675c0d3b4..78cb1b79616 100644 --- a/xarray/core/indexes.py +++ b/xarray/core/indexes.py @@ -12,6 +12,7 @@ def remove_unused(index): """ Remove unused levels if CategoricalIndex """ if isinstance(index, pd.MultiIndex): + index = index.remove_unused_levels() # if it contains CategoricalIndex, we need to remove unused categories # manually. See https://github.com/pandas-dev/pandas/issues/30846 if any(isinstance(lev, pd.CategoricalIndex) for lev in index.levels): diff --git a/xarray/tests/test_dataset.py b/xarray/tests/test_dataset.py index 599d7b12f80..5d7472c8130 100644 --- a/xarray/tests/test_dataset.py +++ b/xarray/tests/test_dataset.py @@ -1400,6 +1400,26 @@ def test_sel_categorical(self): expected = ds.isel(ind=1) assert_identical(expected, actual) + def test_categorical_index(self): + cat = pd.CategoricalIndex( + ["foo", "bar", "foo"], + categories=["foo", "bar", "baz", + "qux", "quux", "corge"]) + ds = xr.Dataset({'var': ('cat', np.arange(3))}, + coords={'cat': ('cat', cat), + 'c': ('cat', [0, 1, 1])}) + # test slice + actual = ds.sel(cat='foo') + expected = ds.isel(cat=[0, 2]) + assert_identical(expected, actual) + # make sure the conversion to the array works + actual = ds.sel(cat='foo')['cat'].values + assert (actual == ['foo', 'foo']).all() + + ds = ds.set_index(index=['cat', 'c']) + actual = ds.unstack('index') + assert actual['var'].shape == (2, 2) + def test_sel_drop(self): data = Dataset({"foo": ("x", [1, 2, 3])}, {"x": [0, 1, 2]}) expected = Dataset({"foo": 1}) From 8d9b6ec39b03743eaef3a4b3922582ac7c6efb3b Mon Sep 17 00:00:00 2001 From: keisukefujii Date: Sat, 11 Jan 2020 11:51:15 +0900 Subject: [PATCH 05/11] black --- xarray/tests/test_dataset.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/xarray/tests/test_dataset.py b/xarray/tests/test_dataset.py index 5d7472c8130..da358b50b7a 100644 --- a/xarray/tests/test_dataset.py +++ b/xarray/tests/test_dataset.py @@ -1403,22 +1403,23 @@ def test_sel_categorical(self): def test_categorical_index(self): cat = pd.CategoricalIndex( ["foo", "bar", "foo"], - categories=["foo", "bar", "baz", - "qux", "quux", "corge"]) - ds = xr.Dataset({'var': ('cat', np.arange(3))}, - coords={'cat': ('cat', cat), - 'c': ('cat', [0, 1, 1])}) + categories=["foo", "bar", "baz", "qux", "quux", "corge"], + ) + ds = xr.Dataset( + {"var": ("cat", np.arange(3))}, + coords={"cat": ("cat", cat), "c": ("cat", [0, 1, 1])}, + ) # test slice - actual = ds.sel(cat='foo') + actual = ds.sel(cat="foo") expected = ds.isel(cat=[0, 2]) assert_identical(expected, actual) # make sure the conversion to the array works - actual = ds.sel(cat='foo')['cat'].values - assert (actual == ['foo', 'foo']).all() + actual = ds.sel(cat="foo")["cat"].values + assert (actual == ["foo", "foo"]).all() - ds = ds.set_index(index=['cat', 'c']) - actual = ds.unstack('index') - assert actual['var'].shape == (2, 2) + ds = ds.set_index(index=["cat", "c"]) + actual = ds.unstack("index") + assert actual["var"].shape == (2, 2) def test_sel_drop(self): data = Dataset({"foo": ("x", [1, 2, 3])}, {"x": [0, 1, 2]}) @@ -3866,8 +3867,8 @@ def test_to_and_from_dataframe(self): def test_from_dataframe_categorical(self): cat = pd.CategoricalDtype( - categories=["foo", "bar", "baz", - "qux", "quux", "corge"]) + categories=["foo", "bar", "baz", "qux", "quux", "corge"] + ) i1 = pd.Series(["foo", "bar", "foo"], dtype=cat) i2 = pd.Series(["bar", "bar", "baz"], dtype=cat) From 262b8d53483c8ffbdfa379fd8c14cd081de103ab Mon Sep 17 00:00:00 2001 From: keisukefujii Date: Sat, 11 Jan 2020 12:04:40 +0900 Subject: [PATCH 06/11] Added a test to make sure raising ValueErrors --- xarray/core/indexing.py | 2 ++ xarray/tests/test_dataset.py | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/xarray/core/indexing.py b/xarray/core/indexing.py index e1e073f3060..df734ba9883 100644 --- a/xarray/core/indexing.py +++ b/xarray/core/indexing.py @@ -176,6 +176,8 @@ def convert_label_indexer(index, label, index_name="", method=None, tolerance=No if isinstance(index, pd.MultiIndex): indexer, new_index = index.get_loc_level(label.item(), level=0) elif isinstance(index, pd.CategoricalIndex): + if method is not None: + raise ValueError("method is not valid with categorical index.") if tolerance is not None: raise ValueError("tolerance is not valid with categorical index.") indexer = index.get_loc(label.item()) diff --git a/xarray/tests/test_dataset.py b/xarray/tests/test_dataset.py index da358b50b7a..eeec7f824c0 100644 --- a/xarray/tests/test_dataset.py +++ b/xarray/tests/test_dataset.py @@ -1400,6 +1400,15 @@ def test_sel_categorical(self): expected = ds.isel(ind=1) assert_identical(expected, actual) + def test_sel_categorical_error(self): + ind = pd.Series(["foo", "bar"], dtype="category") + df = pd.DataFrame({"ind": ind, "values": [1, 2]}) + ds = df.set_index("ind").to_xarray() + with pytest.raises(ValueError): + ds.sel(ind="bar", method="nearest") + with pytest.raises(ValueError): + ds.sel(ind="bar", tolerance="nearest") + def test_categorical_index(self): cat = pd.CategoricalIndex( ["foo", "bar", "foo"], From b8720a40cfd52be19b46e078732de0948b178185 Mon Sep 17 00:00:00 2001 From: keisukefujii Date: Sat, 11 Jan 2020 12:22:38 +0900 Subject: [PATCH 07/11] remove unnecessary print --- xarray/tests/test_dataset.py | 1 - 1 file changed, 1 deletion(-) diff --git a/xarray/tests/test_dataset.py b/xarray/tests/test_dataset.py index eeec7f824c0..72e573f6109 100644 --- a/xarray/tests/test_dataset.py +++ b/xarray/tests/test_dataset.py @@ -3886,7 +3886,6 @@ def test_from_dataframe_categorical(self): assert len(ds["i1"]) == 3 ds = df.set_index(["i1", "i2"]).to_xarray() - print(ds) assert len(ds["i1"]) == 2 assert len(ds["i2"]) == 2 From 57ca90ed210120fc3bea145dfb8290ba4e319340 Mon Sep 17 00:00:00 2001 From: keisukefujii Date: Tue, 14 Jan 2020 18:37:59 +0900 Subject: [PATCH 08/11] added a test for reindex --- xarray/tests/test_dataset.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/xarray/tests/test_dataset.py b/xarray/tests/test_dataset.py index 72e573f6109..88fdb239083 100644 --- a/xarray/tests/test_dataset.py +++ b/xarray/tests/test_dataset.py @@ -1424,12 +1424,24 @@ def test_categorical_index(self): assert_identical(expected, actual) # make sure the conversion to the array works actual = ds.sel(cat="foo")["cat"].values - assert (actual == ["foo", "foo"]).all() + assert (actual == np.array(["foo", "foo"])).all() ds = ds.set_index(index=["cat", "c"]) actual = ds.unstack("index") assert actual["var"].shape == (2, 2) + def test_categorical_reindex(self): + cat = pd.CategoricalIndex( + ["foo", "bar", "baz"], + categories=["foo", "bar", "baz", "qux", "quux", "corge"], + ) + ds = xr.Dataset( + {"var": ("cat", np.arange(3))}, + coords={"cat": ("cat", cat), "c": ("cat", [0, 1, 2])}, + ) + actual = ds.reindex(cat=["foo"])["cat"].values + assert (actual == np.array(["foo"])).all() + def test_sel_drop(self): data = Dataset({"foo": ("x", [1, 2, 3])}, {"x": [0, 1, 2]}) expected = Dataset({"foo": 1}) From d33818571990f8a23c13b7fff453223d9549bfe1 Mon Sep 17 00:00:00 2001 From: keisukefujii Date: Mon, 20 Jan 2020 08:41:23 +0900 Subject: [PATCH 09/11] Fix according to reviews --- doc/whats-new.rst | 2 +- xarray/core/dataset.py | 6 +++--- xarray/core/indexes.py | 8 +++++--- xarray/core/indexing.py | 4 ++-- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/doc/whats-new.rst b/doc/whats-new.rst index b925fe2836d..f1692a4e495 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -25,7 +25,7 @@ Breaking changes New Features ~~~~~~~~~~~~ -- Now :py:func:`sel` works dataarray / dataset with pd.CategoricalIndex. (:issue:`3669`) +- :py:meth:`DataArray.sel` and :py:meth:`Dataset.sel` now support :py:class:`pandas.CategoricalIndex`. (:issue:`3669`) By `Keisuke Fujii `_. - Implement :py:func:`median` and :py:func:`nanmedian` for dask arrays. This works by rechunking to a single chunk along all reduction axes. (:issue:`2999`). diff --git a/xarray/core/dataset.py b/xarray/core/dataset.py index 23e9c4564ca..031d14c8c20 100644 --- a/xarray/core/dataset.py +++ b/xarray/core/dataset.py @@ -64,7 +64,7 @@ default_indexes, isel_variable_and_index, propagate_indexes, - remove_unused, + remove_unused_levels_categories, roll_index, ) from .indexing import is_fancy_indexer @@ -3407,7 +3407,7 @@ def ensure_stackable(val): def _unstack_once(self, dim: Hashable, fill_value, sparse) -> "Dataset": index = self.get_index(dim) - index = remove_unused(index) + index = remove_unused_levels_categories(index) full_idx = pd.MultiIndex.from_product(index.levels, names=index.names) # take a shortcut in case the MultiIndex was not modified. @@ -4547,7 +4547,7 @@ def from_dataframe(cls, dataframe: pd.DataFrame, sparse: bool = False) -> "Datas if not dataframe.columns.is_unique: raise ValueError("cannot convert DataFrame with non-unique columns") - idx = remove_unused(dataframe.index) + idx = remove_unused_levels_categories(dataframe.index) dataframe = dataframe.set_index(idx) obj = cls() diff --git a/xarray/core/indexes.py b/xarray/core/indexes.py index 78cb1b79616..42776bc7b37 100644 --- a/xarray/core/indexes.py +++ b/xarray/core/indexes.py @@ -9,8 +9,10 @@ from .variable import Variable -def remove_unused(index): - """ Remove unused levels if CategoricalIndex """ +def remove_unused_levels_categories(index): + """ + Remove unused levels from MultiIndex and unused categories from CategoricalIndex + """ if isinstance(index, pd.MultiIndex): index = index.remove_unused_levels() # if it contains CategoricalIndex, we need to remove unused categories @@ -22,7 +24,7 @@ def remove_unused(index): level = level[index.codes[i]].remove_unused_categories() levels.append(level) index = pd.MultiIndex.from_arrays(levels, names=index.names) - if isinstance(index, pd.CategoricalIndex): + elif isinstance(index, pd.CategoricalIndex): index = index.remove_unused_categories() return index diff --git a/xarray/core/indexing.py b/xarray/core/indexing.py index df734ba9883..2c359eb1bf2 100644 --- a/xarray/core/indexing.py +++ b/xarray/core/indexing.py @@ -177,9 +177,9 @@ def convert_label_indexer(index, label, index_name="", method=None, tolerance=No indexer, new_index = index.get_loc_level(label.item(), level=0) elif isinstance(index, pd.CategoricalIndex): if method is not None: - raise ValueError("method is not valid with categorical index.") + raise ValueError("'method' is not a valid kwarg when indexing using a CategoricalIndex.") if tolerance is not None: - raise ValueError("tolerance is not valid with categorical index.") + raise ValueError("'tolerance' is not a valid kwarg when indexing using a CategoricalIndex.") indexer = index.get_loc(label.item()) else: indexer = index.get_loc( From 5cdf82e6d087b9482c47812695214b0c3f28b6af Mon Sep 17 00:00:00 2001 From: dcherian Date: Fri, 24 Jan 2020 17:58:31 -0700 Subject: [PATCH 10/11] blacken --- xarray/core/indexing.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/xarray/core/indexing.py b/xarray/core/indexing.py index 2c359eb1bf2..4e58be1ad2f 100644 --- a/xarray/core/indexing.py +++ b/xarray/core/indexing.py @@ -177,9 +177,13 @@ def convert_label_indexer(index, label, index_name="", method=None, tolerance=No indexer, new_index = index.get_loc_level(label.item(), level=0) elif isinstance(index, pd.CategoricalIndex): if method is not None: - raise ValueError("'method' is not a valid kwarg when indexing using a CategoricalIndex.") + raise ValueError( + "'method' is not a valid kwarg when indexing using a CategoricalIndex." + ) if tolerance is not None: - raise ValueError("'tolerance' is not a valid kwarg when indexing using a CategoricalIndex.") + raise ValueError( + "'tolerance' is not a valid kwarg when indexing using a CategoricalIndex." + ) indexer = index.get_loc(label.item()) else: indexer = index.get_loc( From 27f35059038c6ab74e6352932ac58759f2aca5b0 Mon Sep 17 00:00:00 2001 From: Keewis Date: Sat, 25 Jan 2020 12:43:19 +0100 Subject: [PATCH 11/11] delete trailing whitespace --- xarray/core/indexes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xarray/core/indexes.py b/xarray/core/indexes.py index 42776bc7b37..06bf08cefd2 100644 --- a/xarray/core/indexes.py +++ b/xarray/core/indexes.py @@ -10,8 +10,8 @@ def remove_unused_levels_categories(index): - """ - Remove unused levels from MultiIndex and unused categories from CategoricalIndex + """ + Remove unused levels from MultiIndex and unused categories from CategoricalIndex """ if isinstance(index, pd.MultiIndex): index = index.remove_unused_levels()