Skip to content

Commit 7659b2d

Browse files
jsignellIllviljanpre-commit-ci[bot]
authored
Order coords to match dims in repr (#10778)
* Order coords to match dims in repr * Update docstrings with new dim-ordered coords * Add tests for _repr_html_ coord ordering * Update what's new * Apply suggestions from code review * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: Illviljan <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent ac43d3b commit 7659b2d

File tree

9 files changed

+82
-33
lines changed

9 files changed

+82
-33
lines changed

doc/whats-new.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ New Features
8686
(:pull:`10624`).
8787
By `Stephan Hoyer <https://github.com/shoyer>`_.
8888

89+
- Coordinates are ordered to match dims when displaying Xarray objects. (:pull:`10778`).
90+
By `Julia Signell <https://github.com/jsignell>`_.
91+
8992
Breaking changes
9093
~~~~~~~~~~~~~~~~
9194

xarray/core/common.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -619,9 +619,9 @@ def assign_coords(
619619
<xarray.Dataset> Size: 360B
620620
Dimensions: (x: 2, y: 2, time: 4)
621621
Coordinates:
622+
* time (time) datetime64[ns] 32B 2014-09-06 ... 2014-09-09
622623
lon (x, y) float64 32B 260.2 260.7 260.2 260.8
623624
lat (x, y) float64 32B 42.25 42.21 42.63 42.59
624-
* time (time) datetime64[ns] 32B 2014-09-06 ... 2014-09-09
625625
reference_time datetime64[ns] 8B 2014-09-05
626626
Dimensions without coordinates: x, y
627627
Data variables:
@@ -633,9 +633,9 @@ def assign_coords(
633633
<xarray.Dataset> Size: 360B
634634
Dimensions: (x: 2, y: 2, time: 4)
635635
Coordinates:
636+
* time (time) datetime64[ns] 32B 2014-09-06 ... 2014-09-09
636637
lon (x, y) float64 32B -99.83 -99.32 -99.79 -99.23
637638
lat (x, y) float64 32B 42.25 42.21 42.63 42.59
638-
* time (time) datetime64[ns] 32B 2014-09-06 ... 2014-09-09
639639
reference_time datetime64[ns] 8B 2014-09-05
640640
Dimensions without coordinates: x, y
641641
Data variables:

xarray/core/dataarray.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -368,9 +368,9 @@ class DataArray(
368368
[[22.60070734, 13.78914233, 14.17424919],
369369
[18.28478802, 16.15234857, 26.63418806]]])
370370
Coordinates:
371+
* time (time) datetime64[ns] 24B 2014-09-06 2014-09-07 2014-09-08
371372
lon (x, y) float64 32B -99.83 -99.32 -99.79 -99.23
372373
lat (x, y) float64 32B 42.25 42.21 42.63 42.59
373-
* time (time) datetime64[ns] 24B 2014-09-06 2014-09-07 2014-09-08
374374
reference_time datetime64[ns] 8B 2014-09-05
375375
Dimensions without coordinates: x, y
376376
Attributes:
@@ -2139,17 +2139,17 @@ def reindex_like(
21392139
<xarray.DataArray (y: 3)> Size: 24B
21402140
array([3, 4, 5])
21412141
Coordinates:
2142-
x int64 8B 20
21432142
* y (y) int64 24B 70 80 90
2143+
x int64 8B 20
21442144
21452145
...so ``b`` in not added here:
21462146
21472147
>>> da1.sel(x=20).reindex_like(da1)
21482148
<xarray.DataArray (y: 3)> Size: 24B
21492149
array([3, 4, 5])
21502150
Coordinates:
2151-
x int64 8B 20
21522151
* y (y) int64 24B 70 80 90
2152+
x int64 8B 20
21532153
21542154
See Also
21552155
--------
@@ -2363,8 +2363,8 @@ def interp(
23632363
[3. , nan, 5.75, nan],
23642364
[5. , nan, 5.25, nan]])
23652365
Coordinates:
2366-
* y (y) int64 32B 10 12 14 16
23672366
* x (x) float64 32B 0.0 0.75 1.25 1.75
2367+
* y (y) int64 32B 10 12 14 16
23682368
23692369
1D nearest interpolation:
23702370
@@ -2375,8 +2375,8 @@ def interp(
23752375
[ 2., 7., 6., nan],
23762376
[ 6., nan, 5., 8.]])
23772377
Coordinates:
2378-
* y (y) int64 32B 10 12 14 16
23792378
* x (x) float64 32B 0.0 0.75 1.25 1.75
2379+
* y (y) int64 32B 10 12 14 16
23802380
23812381
1D linear extrapolation:
23822382
@@ -2391,8 +2391,8 @@ def interp(
23912391
[ 8. , nan, 4.5, nan],
23922392
[12. , nan, 3.5, nan]])
23932393
Coordinates:
2394-
* y (y) int64 32B 10 12 14 16
23952394
* x (x) float64 32B 1.0 1.5 2.5 3.5
2395+
* y (y) int64 32B 10 12 14 16
23962396
23972397
2D linear interpolation:
23982398
@@ -2639,8 +2639,8 @@ def swap_dims(
26392639
<xarray.DataArray (y: 2)> Size: 16B
26402640
array([0, 1])
26412641
Coordinates:
2642-
x (y) <U1 8B 'a' 'b'
26432642
* y (y) int64 16B 0 1
2643+
x (y) <U1 8B 'a' 'b'
26442644
26452645
>>> arr.swap_dims({"x": "z"})
26462646
<xarray.DataArray (z: 2)> Size: 16B
@@ -5369,8 +5369,8 @@ def quantile(
53695369
[3.6 , 5.75, 6. , 1.7 ],
53705370
[6.5 , 7.3 , 9.4 , 1.9 ]])
53715371
Coordinates:
5372-
* y (y) float64 32B 1.0 1.5 2.0 2.5
53735372
* quantile (quantile) float64 24B 0.0 0.5 1.0
5373+
* y (y) float64 32B 1.0 1.5 2.0 2.5
53745374
53755375
References
53765376
----------

xarray/core/dataset.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -315,10 +315,10 @@ class Dataset(
315315
<xarray.Dataset> Size: 552B
316316
Dimensions: (loc: 2, instrument: 3, time: 4)
317317
Coordinates:
318-
lon (loc) float64 16B -99.83 -99.32
319-
lat (loc) float64 16B 42.25 42.21
320318
* instrument (instrument) <U8 96B 'manufac1' 'manufac2' 'manufac3'
321319
* time (time) datetime64[ns] 32B 2014-09-06 ... 2014-09-09
320+
lon (loc) float64 16B -99.83 -99.32
321+
lat (loc) float64 16B 42.25 42.21
322322
reference_time datetime64[ns] 8B 2014-09-05
323323
Dimensions without coordinates: loc
324324
Data variables:
@@ -1806,8 +1806,8 @@ def set_coords(self, names: Hashable | Iterable[Hashable]) -> Self:
18061806
<xarray.Dataset> Size: 48B
18071807
Dimensions: (time: 3)
18081808
Coordinates:
1809-
pressure (time) float64 24B 1.013 1.2 3.5
18101809
* time (time) datetime64[ns] 24B 2023-01-01 2023-01-02 2023-01-03
1810+
pressure (time) float64 24B 1.013 1.2 3.5
18111811
Data variables:
18121812
*empty*
18131813
@@ -3805,8 +3805,8 @@ def interp(
38053805
<xarray.Dataset> Size: 224B
38063806
Dimensions: (x: 4, y: 4)
38073807
Coordinates:
3808-
* y (y) int64 32B 10 12 14 16
38093808
* x (x) float64 32B 0.0 0.75 1.25 1.75
3809+
* y (y) int64 32B 10 12 14 16
38103810
Data variables:
38113811
a (x) float64 32B 5.0 6.5 6.25 4.75
38123812
b (x, y) float64 128B 1.0 4.0 2.0 nan 1.75 ... nan 5.0 nan 5.25 nan
@@ -3817,8 +3817,8 @@ def interp(
38173817
<xarray.Dataset> Size: 224B
38183818
Dimensions: (x: 4, y: 4)
38193819
Coordinates:
3820-
* y (y) int64 32B 10 12 14 16
38213820
* x (x) float64 32B 0.0 0.75 1.25 1.75
3821+
* y (y) int64 32B 10 12 14 16
38223822
Data variables:
38233823
a (x) float64 32B 5.0 7.0 7.0 4.0
38243824
b (x, y) float64 128B 1.0 4.0 2.0 9.0 2.0 7.0 ... nan 6.0 nan 5.0 8.0
@@ -3833,8 +3833,8 @@ def interp(
38333833
<xarray.Dataset> Size: 224B
38343834
Dimensions: (x: 4, y: 4)
38353835
Coordinates:
3836-
* y (y) int64 32B 10 12 14 16
38373836
* x (x) float64 32B 1.0 1.5 2.5 3.5
3837+
* y (y) int64 32B 10 12 14 16
38383838
Data variables:
38393839
a (x) float64 32B 7.0 5.5 2.5 -0.5
38403840
b (x, y) float64 128B 2.0 7.0 6.0 nan 4.0 ... nan 12.0 nan 3.5 nan
@@ -4358,8 +4358,8 @@ def swap_dims(
43584358
<xarray.Dataset> Size: 56B
43594359
Dimensions: (y: 2)
43604360
Coordinates:
4361-
x (y) <U1 8B 'a' 'b'
43624361
* y (y) int64 16B 0 1
4362+
x (y) <U1 8B 'a' 'b'
43634363
Data variables:
43644364
a (y) int64 16B 5 7
43654365
b (y) float64 16B 0.1 2.4
@@ -8208,8 +8208,8 @@ def quantile(
82088208
<xarray.Dataset> Size: 152B
82098209
Dimensions: (quantile: 3, y: 4)
82108210
Coordinates:
8211-
* y (y) float64 32B 1.0 1.5 2.0 2.5
82128211
* quantile (quantile) float64 24B 0.0 0.5 1.0
8212+
* y (y) float64 32B 1.0 1.5 2.0 2.5
82138213
Data variables:
82148214
a (quantile, y) float64 96B 0.7 4.2 2.6 1.5 3.6 ... 6.5 7.3 9.4 1.9
82158215
@@ -8682,9 +8682,9 @@ def filter_by_attrs(self, **kwargs) -> Self:
86828682
<xarray.Dataset> Size: 192B
86838683
Dimensions: (x: 2, y: 2, time: 3)
86848684
Coordinates:
8685+
* time (time) datetime64[ns] 24B 2014-09-06 2014-09-07 2014-09-08
86858686
lon (x, y) float64 32B -99.83 -99.32 -99.79 -99.23
86868687
lat (x, y) float64 32B 42.25 42.21 42.63 42.59
8687-
* time (time) datetime64[ns] 24B 2014-09-06 2014-09-07 2014-09-08
86888688
reference_time datetime64[ns] 8B 2014-09-05
86898689
Dimensions without coordinates: x, y
86908690
Data variables:
@@ -8697,9 +8697,9 @@ def filter_by_attrs(self, **kwargs) -> Self:
86978697
<xarray.Dataset> Size: 288B
86988698
Dimensions: (x: 2, y: 2, time: 3)
86998699
Coordinates:
8700+
* time (time) datetime64[ns] 24B 2014-09-06 2014-09-07 2014-09-08
87008701
lon (x, y) float64 32B -99.83 -99.32 -99.79 -99.23
87018702
lat (x, y) float64 32B 42.25 42.21 42.63 42.59
8702-
* time (time) datetime64[ns] 24B 2014-09-06 2014-09-07 2014-09-08
87038703
reference_time datetime64[ns] 8B 2014-09-05
87048704
Dimensions without coordinates: x, y
87058705
Data variables:
@@ -9370,8 +9370,8 @@ def argmin(self, dim: Hashable | None = None, **kwargs) -> Self:
93709370
<xarray.DataArray 'student' (test: 3)> Size: 84B
93719371
array(['Bob', 'Bob', 'Alice'], dtype='<U7')
93729372
Coordinates:
9373-
student (test) <U7 84B 'Bob' 'Bob' 'Alice'
93749373
* test (test) <U6 72B 'Test 1' 'Test 2' 'Test 3'
9374+
student (test) <U7 84B 'Bob' 'Bob' 'Alice'
93759375
93769376
>>> min_score_in_english = dataset["student"].isel(
93779377
... student=argmin_indices["english_scores"]
@@ -9380,8 +9380,8 @@ def argmin(self, dim: Hashable | None = None, **kwargs) -> Self:
93809380
<xarray.DataArray 'student' (test: 3)> Size: 84B
93819381
array(['Charlie', 'Bob', 'Charlie'], dtype='<U7')
93829382
Coordinates:
9383-
student (test) <U7 84B 'Charlie' 'Bob' 'Charlie'
93849383
* test (test) <U6 72B 'Test 1' 'Test 2' 'Test 3'
9384+
student (test) <U7 84B 'Charlie' 'Bob' 'Charlie'
93859385
93869386
See Also
93879387
--------

xarray/core/formatting.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,8 +446,12 @@ def _mapping_repr(
446446
def coords_repr(coords: AbstractCoordinates, col_width=None, max_rows=None):
447447
if col_width is None:
448448
col_width = _calculate_col_width(coords)
449+
dims = tuple(coords._data.dims)
450+
dim_ordered_coords = sorted(
451+
coords.items(), key=lambda x: dims.index(x[0]) if x[0] in dims else len(dims)
452+
)
449453
return _mapping_repr(
450-
coords,
454+
dict(dim_ordered_coords),
451455
title="Coordinates",
452456
summarizer=summarize_variable,
453457
expand_option_name="display_expand_coords",

xarray/core/formatting_html.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,11 @@ def summarize_variable(name, var, is_index=False, dtype=None) -> str:
117117

118118
def summarize_coords(variables) -> str:
119119
li_items = []
120-
for k, v in variables.items():
120+
dims = tuple(variables._data.dims)
121+
dim_ordered_coords = sorted(
122+
variables.items(), key=lambda x: dims.index(x[0]) if x[0] in dims else len(dims)
123+
)
124+
for k, v in dim_ordered_coords:
121125
li_content = summarize_variable(k, v, is_index=k in variables.xindexes)
122126
li_items.append(f"<li class='xr-var-item'>{li_content}</li>")
123127

xarray/core/groupby.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -750,8 +750,8 @@ def shuffle_to_chunks(self, chunks: T_Chunks = None) -> T_Xarray:
750750
<xarray.DataArray 'a' (x: 4)> Size: 32B
751751
array([9., 3., 4., 5.])
752752
Coordinates:
753-
quantile float64 8B 0.5
754753
* x (x) int64 32B 0 1 2 3
754+
quantile float64 8B 0.5
755755
756756
See Also
757757
--------
@@ -1313,15 +1313,15 @@ def quantile(
13131313
array([[0.7, 4.2, 0.7, 1.5],
13141314
[6.5, 7.3, 2.6, 1.9]])
13151315
Coordinates:
1316+
* x (x) int64 16B 0 1
13161317
* y (y) int64 32B 1 1 2 2
13171318
quantile float64 8B 0.0
1318-
* x (x) int64 16B 0 1
13191319
>>> ds.groupby("y").quantile(0, dim=...)
13201320
<xarray.Dataset> Size: 40B
13211321
Dimensions: (y: 2)
13221322
Coordinates:
1323-
quantile float64 8B 0.0
13241323
* y (y) int64 16B 1 2
1324+
quantile float64 8B 0.0
13251325
Data variables:
13261326
a (y) float64 16B 0.7 0.7
13271327
>>> da.groupby("x").quantile([0, 0.5, 1])
@@ -1336,15 +1336,15 @@ def quantile(
13361336
[2.6 , 2.6 , 2.6 ],
13371337
[1.9 , 1.9 , 1.9 ]]])
13381338
Coordinates:
1339+
* x (x) int64 16B 0 1
13391340
* y (y) int64 32B 1 1 2 2
13401341
* quantile (quantile) float64 24B 0.0 0.5 1.0
1341-
* x (x) int64 16B 0 1
13421342
>>> ds.groupby("y").quantile([0, 0.5, 1], dim=...)
13431343
<xarray.Dataset> Size: 88B
13441344
Dimensions: (y: 2, quantile: 3)
13451345
Coordinates:
1346-
* quantile (quantile) float64 24B 0.0 0.5 1.0
13471346
* y (y) int64 16B 1 2
1347+
* quantile (quantile) float64 24B 0.0 0.5 1.0
13481348
Data variables:
13491349
a (y, quantile) float64 48B 0.7 5.35 8.4 0.7 2.25 9.4
13501350

xarray/structure/concat.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -224,8 +224,8 @@ def concat(
224224
array([[0, 1, 2],
225225
[3, 4, 5]])
226226
Coordinates:
227-
x (new_dim) <U1 8B 'a' 'b'
228227
* y (y) int64 24B 10 20 30
228+
x (new_dim) <U1 8B 'a' 'b'
229229
Dimensions without coordinates: new_dim
230230
231231
>>> xr.concat(
@@ -237,9 +237,9 @@ def concat(
237237
array([[0, 1, 2],
238238
[3, 4, 5]])
239239
Coordinates:
240-
x (new_dim) <U1 8B 'a' 'b'
241-
* y (y) int64 24B 10 20 30
242240
* new_dim (new_dim) int64 16B -90 -100
241+
* y (y) int64 24B 10 20 30
242+
x (new_dim) <U1 8B 'a' 'b'
243243
244244
# Concatenate a scalar variable along a new dimension of the same name with and without creating a new index
245245

xarray/tests/test_formatting_html.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ def dataset() -> xr.Dataset:
106106
"tmin": (("time", "location"), tmin_values),
107107
"tmax": (("time", "location"), tmax_values),
108108
},
109-
{"time": times, "location": ["<IA>", "IN", "IL"]},
109+
{"location": ["<IA>", "IN", "IL"], "time": times},
110110
attrs={"description": "Test data."},
111111
)
112112

@@ -186,6 +186,33 @@ def test_repr_of_dataarray() -> None:
186186
assert "Attributes" not in formatted
187187

188188

189+
def test_repr_coords_order_of_datarray() -> None:
190+
da1 = xr.DataArray(
191+
np.empty((2, 2)),
192+
coords={"foo": [0, 1], "bar": [0, 1]},
193+
dims=["foo", "bar"],
194+
)
195+
da2 = xr.DataArray(
196+
np.empty((2, 2)),
197+
coords={"bar": [0, 1], "foo": [0, 1]},
198+
dims=["bar", "foo"],
199+
)
200+
ds = xr.Dataset({"da1": da1, "da2": da2})
201+
202+
bar_line = (
203+
"<span class='xr-has-index'>bar</span></div><div class='xr-var-dims'>(bar)"
204+
)
205+
foo_line = (
206+
"<span class='xr-has-index'>foo</span></div><div class='xr-var-dims'>(foo)"
207+
)
208+
209+
formatted_da1 = fh.array_repr(ds.da1)
210+
assert formatted_da1.index(foo_line) < formatted_da1.index(bar_line)
211+
212+
formatted_da2 = fh.array_repr(ds.da2)
213+
assert formatted_da2.index(bar_line) < formatted_da2.index(foo_line)
214+
215+
189216
def test_repr_of_multiindex(multiindex: xr.Dataset) -> None:
190217
formatted = fh.dataset_repr(multiindex)
191218
assert "(x)" in formatted
@@ -231,6 +258,17 @@ def test_repr_text_fallback(dataset: xr.Dataset) -> None:
231258
assert "<pre class='xr-text-repr-fallback'>" in formatted
232259

233260

261+
def test_repr_coords_order_of_dataset() -> None:
262+
ds = xr.Dataset()
263+
ds.coords["as"] = 10
264+
ds["var"] = xr.DataArray(np.ones((10,)), dims="x", coords={"x": np.arange(10)})
265+
formatted = fh.dataset_repr(ds)
266+
267+
x_line = "<span class='xr-has-index'>x</span></div><div class='xr-var-dims'>(x)"
268+
as_line = "<span>as</span></div><div class='xr-var-dims'>()"
269+
assert formatted.index(x_line) < formatted.index(as_line)
270+
271+
234272
def test_variable_repr_html() -> None:
235273
v = xr.Variable(["time", "x"], [[1, 2, 3], [4, 5, 6]], {"foo": "bar"})
236274
assert hasattr(v, "_repr_html_")

0 commit comments

Comments
 (0)