Skip to content

Commit 080caf4

Browse files
keewisdcherian
authored andcommitted
Support swap_dims to dimension names that are not existing variables (#3636)
* test that swapping to a non-existing name works * don't try to get a variable if the variable does not exist * don't add dimensions to coord_names if they are not existing variables * add whats-new.rst entry * update the documentation
1 parent 8fc9ece commit 080caf4

File tree

5 files changed

+35
-6
lines changed

5 files changed

+35
-6
lines changed

doc/whats-new.rst

+3
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ New Features
3737
- Added the ``count`` reduction method to both :py:class:`~core.rolling.DatasetCoarsen`
3838
and :py:class:`~core.rolling.DataArrayCoarsen` objects. (:pull:`3500`)
3939
By `Deepak Cherian <https://github.com/dcherian>`_
40+
- :py:meth:`Dataset.swap_dims` and :py:meth:`DataArray.swap_dims`
41+
now allow swapping to dimension names that don't exist yet. (:pull:`3636`)
42+
By `Justus Magin <https://github.com/keewis>`_.
4043
- Extend :py:class:`core.accessor_dt.DatetimeAccessor` properties
4144
and support `.dt` accessor for timedelta
4245
via :py:class:`core.accessor_dt.TimedeltaAccessor` (:pull:`3612`)

xarray/core/dataarray.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -1480,8 +1480,7 @@ def swap_dims(self, dims_dict: Mapping[Hashable, Hashable]) -> "DataArray":
14801480
----------
14811481
dims_dict : dict-like
14821482
Dictionary whose keys are current dimension names and whose values
1483-
are new names. Each value must already be a coordinate on this
1484-
array.
1483+
are new names.
14851484
14861485
Returns
14871486
-------
@@ -1504,6 +1503,13 @@ def swap_dims(self, dims_dict: Mapping[Hashable, Hashable]) -> "DataArray":
15041503
Coordinates:
15051504
x (y) <U1 'a' 'b'
15061505
* y (y) int64 0 1
1506+
>>> arr.swap_dims({"x": "z"})
1507+
<xarray.DataArray (z: 2)>
1508+
array([0, 1])
1509+
Coordinates:
1510+
x (z) <U1 'a' 'b'
1511+
y (z) int64 0 1
1512+
Dimensions without coordinates: z
15071513
15081514
See Also
15091515
--------

xarray/core/dataset.py

+13-4
Original file line numberDiff line numberDiff line change
@@ -2875,8 +2875,7 @@ def swap_dims(
28752875
----------
28762876
dims_dict : dict-like
28772877
Dictionary whose keys are current dimension names and whose values
2878-
are new names. Each value must already be a variable in the
2879-
dataset.
2878+
are new names.
28802879
28812880
Returns
28822881
-------
@@ -2905,6 +2904,16 @@ def swap_dims(
29052904
Data variables:
29062905
a (y) int64 5 7
29072906
b (y) float64 0.1 2.4
2907+
>>> ds.swap_dims({"x": "z"})
2908+
<xarray.Dataset>
2909+
Dimensions: (z: 2)
2910+
Coordinates:
2911+
x (z) <U1 'a' 'b'
2912+
y (z) int64 0 1
2913+
Dimensions without coordinates: z
2914+
Data variables:
2915+
a (z) int64 5 7
2916+
b (z) float64 0.1 2.4
29082917
29092918
See Also
29102919
--------
@@ -2921,7 +2930,7 @@ def swap_dims(
29212930
"cannot swap from dimension %r because it is "
29222931
"not an existing dimension" % k
29232932
)
2924-
if self.variables[v].dims != (k,):
2933+
if v in self.variables and self.variables[v].dims != (k,):
29252934
raise ValueError(
29262935
"replacement dimension %r is not a 1D "
29272936
"variable along the old dimension %r" % (v, k)
@@ -2930,7 +2939,7 @@ def swap_dims(
29302939
result_dims = {dims_dict.get(dim, dim) for dim in self.dims}
29312940

29322941
coord_names = self._coord_names.copy()
2933-
coord_names.update(dims_dict.values())
2942+
coord_names.update({dim for dim in dims_dict.values() if dim in self.variables})
29342943

29352944
variables: Dict[Hashable, Variable] = {}
29362945
indexes: Dict[Hashable, pd.Index] = {}

xarray/tests/test_dataarray.py

+5
Original file line numberDiff line numberDiff line change
@@ -1530,6 +1530,11 @@ def test_swap_dims(self):
15301530
actual = array.swap_dims({"x": "y"})
15311531
assert_identical(expected, actual)
15321532

1533+
array = DataArray(np.random.randn(3), {"x": list("abc")}, "x")
1534+
expected = DataArray(array.values, {"x": ("y", list("abc"))}, dims="y")
1535+
actual = array.swap_dims({"x": "y"})
1536+
assert_identical(expected, actual)
1537+
15331538
def test_expand_dims_error(self):
15341539
array = DataArray(
15351540
np.random.randn(3, 4),

xarray/tests/test_dataset.py

+6
Original file line numberDiff line numberDiff line change
@@ -2533,6 +2533,12 @@ def test_swap_dims(self):
25332533
with raises_regex(ValueError, "replacement dimension"):
25342534
original.swap_dims({"x": "z"})
25352535

2536+
expected = Dataset(
2537+
{"y": ("u", list("abc")), "z": 42}, coords={"x": ("u", [1, 2, 3])}
2538+
)
2539+
actual = original.swap_dims({"x": "u"})
2540+
assert_identical(expected, actual)
2541+
25362542
def test_expand_dims_error(self):
25372543
original = Dataset(
25382544
{

0 commit comments

Comments
 (0)