diff --git a/doc/whats-new.rst b/doc/whats-new.rst index 2332f7f236b..595b42f9195 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -36,7 +36,10 @@ Breaking changes Bug fixes ~~~~~~~~~ - +- Fix for :py:meth:`DataSet.diff` and consequently :py:meth:`DataArray.diff` to + raise a KeyError when `diff` is parameterized with a dimension that does not + exist in callee's DataSet/DataArray. (:issue:`7748`) + By `Nathan Redmond `_. Internal Changes ~~~~~~~~~~~~~~~~ diff --git a/xarray/core/dataset.py b/xarray/core/dataset.py index 96f3be00995..ac469b4b007 100644 --- a/xarray/core/dataset.py +++ b/xarray/core/dataset.py @@ -7726,6 +7726,7 @@ def diff( n: int = 1, *, label: Literal["upper", "lower"] = "upper", + dims_found=False, ) -> Self: """Calculate the n-th order discrete difference along given axis. @@ -7798,14 +7799,25 @@ def diff( variables[name] = var.isel(slice_end) - var.isel(slice_start) else: variables[name] = var.isel(slice_new) + dims_found = True else: variables[name] = var difference = self._replace_with_new_dims(variables, indexes=indexes) if n > 1: - return difference.diff(dim, n - 1) + return difference.diff(dim, n - 1, dims_found=dims_found) else: + if dims_found: + return difference + else: + from warnings import warn + + warn( + "Expected dim to be present in at least one DataArray found in DataSet, " + "dim provided not present. This will raise a KeyError in the future.", + DeprecationWarning, + ) return difference def shift( diff --git a/xarray/tests/test_dataarray.py b/xarray/tests/test_dataarray.py index 26a4268c8b7..774d9e6ff2b 100644 --- a/xarray/tests/test_dataarray.py +++ b/xarray/tests/test_dataarray.py @@ -3861,6 +3861,12 @@ def test_dataarray_diff_n1(self) -> None: expected = DataArray(np.diff(da.values, axis=1), dims=["x", "y"]) assert_equal(expected, actual) + def test_dataarray_diff_dim_nonexist(self) -> None: + # uncomment this code for test corresponding to pushed changes + # with pytest.raises(KeyError, match=r"dim provided not present"): + # DataArray(np.random.randn(3, 4), dims=["x", "y"]).diff("z") + pass + def test_coordinate_diff(self) -> None: # regression test for GH634 arr = DataArray(range(0, 20, 2), dims=["lon"], coords=[range(10)]) diff --git a/xarray/tests/test_dataset.py b/xarray/tests/test_dataset.py index a948fafc815..865cb6e185f 100644 --- a/xarray/tests/test_dataset.py +++ b/xarray/tests/test_dataset.py @@ -6040,6 +6040,13 @@ def test_dataset_diff_n2(self) -> None: expected.coords["numbers"] = ("dim3", ds["numbers"].values) assert_equal(expected, actual) + def test_dataset_diff_dim_nonexist(self) -> None: + # uncomment this code for test corresponding to pushed changes + # ds = create_test_data(seed=1) + # with pytest.raises(KeyError, match=r"dim provided not present"): + # ds.diff("dim4") + pass + def test_dataset_diff_exception_n_neg(self) -> None: ds = create_test_data(seed=1) with pytest.raises(ValueError, match=r"must be non-negative"):