@@ -17,6 +17,90 @@ New Features
1717Breaking changes
1818~~~~~~~~~~~~~~~~
1919
20+ - **All xarray operations now preserve attributes by default ** (:issue: `3891 `, :issue: `2582 `).
21+ Previously, operations would drop attributes unless explicitly told to preserve them via ``keep_attrs=True ``.
22+ This aligns xarray with the common scientific workflow where metadata preservation is essential.
23+
24+ **What changed: **
25+
26+ .. code-block :: python
27+
28+ # Before (xarray <2025.09.1):
29+ data = xr.DataArray([1 , 2 , 3 ], attrs = {" units" : " meters" , " long_name" : " height" })
30+ result = data.mean()
31+ result.attrs # {} - Attributes lost!
32+
33+ # After (xarray ≥2025.09.1):
34+ data = xr.DataArray([1 , 2 , 3 ], attrs = {" units" : " meters" , " long_name" : " height" })
35+ result = data.mean()
36+ result.attrs # {"units": "meters", "long_name": "height"} - Attributes preserved!
37+
38+ **Affected operations include: **
39+
40+ *Computational operations: *
41+
42+ - Reductions: ``mean() ``, ``sum() ``, ``std() ``, ``var() ``, ``min() ``, ``max() ``, ``median() ``, ``quantile() ``, etc.
43+ - Rolling windows: ``rolling().mean() ``, ``rolling().sum() ``, etc.
44+ - Groupby: ``groupby().mean() ``, ``groupby().sum() ``, etc.
45+ - Resampling: ``resample().mean() ``, etc.
46+ - Weighted: ``weighted().mean() ``, ``weighted().sum() ``, etc.
47+ - ``apply_ufunc() `` and NumPy universal functions
48+
49+ *Binary operations: *
50+
51+ - Arithmetic: ``+ ``, ``- ``, ``* ``, ``/ ``, ``** ``, ``// ``, ``% `` (attributes from left operand)
52+ - Comparisons: ``< ``, ``> ``, ``== ``, ``!= ``, ``<= ``, ``>= `` (attributes from left operand)
53+ - With scalars: ``data * 2 ``, ``10 - data `` (preserves data's attributes)
54+
55+ *Data manipulation: *
56+
57+ - Missing data: ``fillna() ``, ``dropna() ``, ``interpolate_na() ``, ``ffill() ``, ``bfill() ``
58+ - Indexing/selection: ``isel() ``, ``sel() ``, ``where() ``, ``clip() ``
59+ - Alignment: ``interp() ``, ``reindex() ``, ``align() ``
60+ - Transformations: ``map() ``, ``pipe() ``, ``assign() ``, ``assign_coords() ``
61+ - Shape operations: ``expand_dims() ``, ``squeeze() ``, ``transpose() ``, ``stack() ``, ``unstack() ``
62+
63+ **Binary operations - attributes from left operand: **
64+
65+ .. code-block :: python
66+
67+ a = xr.DataArray([1 , 2 ], attrs = {" source" : " sensor_a" })
68+ b = xr.DataArray([3 , 4 ], attrs = {" source" : " sensor_b" })
69+ (a + b).attrs # {"source": "sensor_a"} - Left operand wins
70+ (b + a).attrs # {"source": "sensor_b"} - Order matters!
71+
72+ **How to restore previous behavior: **
73+
74+ 1. **Globally for your entire script: **
75+
76+ .. code-block :: python
77+
78+ import xarray as xr
79+
80+ xr.set_options(keep_attrs = False ) # Affects all subsequent operations
81+
82+ 2. **For specific operations: **
83+
84+ .. code-block :: python
85+
86+ result = data.mean(dim = " time" , keep_attrs = False )
87+
88+ 3. **For code blocks: **
89+
90+ .. code-block :: python
91+
92+ with xr.set_options(keep_attrs = False ):
93+ # All operations in this block drop attrs
94+ result = data1 + data2
95+
96+ 4. **Remove attributes after operations: **
97+
98+ .. code-block :: python
99+
100+ result = data.mean().drop_attrs()
101+
102+ By `Maximilian Roos <https://github.com/max-sixty >`_.
103+
20104- :py:meth: `Dataset.update ` now returns ``None ``, instead of the updated dataset. This
21105 completes the deprecation cycle started in version 0.17. The method still updates the
22106 dataset in-place. (:issue: `10167 `)
0 commit comments