Skip to content

Commit 601c262

Browse files
authored
Shortened display of NumPy arrays in DataArray.__repr__ (#1207)
* Shortened display of NumPy arrays in DataArray.__repr__ This shortens the array portion of DataArray repr to reasonable lengths for high dimensional arrays: Array | Old length | New length ------------------------------+------------+----------- np.random.randn(500) | 167 | 1 np.random.randn(20, 20) | 150 | 7 np.random.randn(5, 10, 15) | 254 | 24 np.random.randn(5, 10, 15, 3) | 248 | 19 air_temperature['air'] | 41 | 24 rasm['Tair'] | 37 | 24 where the last two entries refer to the corresponding datasets loaded from `xarray.tutorial.load_dataset`. Importantly, this change does not preclude future improvements, such as those suggested in GH1044. * fix spelling * a little more explanation in what's new
1 parent fec5bac commit 601c262

File tree

3 files changed

+57
-1
lines changed

3 files changed

+57
-1
lines changed

doc/whats-new.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ Breaking changes
8484
- By default ``to_netcdf()`` add a ``_FillValue = NaN`` attributes to float types.
8585
By `Frederic Laliberte <https://github.com/laliberte>`_.
8686

87+
- ``repr`` on ``DataArray`` objects uses an shortened display for NumPy array
88+
data that is less likely to overflow onto multiple pages (:issue:`1207`).
89+
By `Stephan Hoyer <https://github.com/shoyer>`_.
90+
8791
- xarray no longer supports python 3.3, versions of dask prior to v0.9.0,
8892
or versions of bottleneck prior to v1.0.
8993

xarray/core/formatting.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from __future__ import absolute_import
88
from __future__ import division
99
from __future__ import print_function
10+
import contextlib
1011
from datetime import datetime, timedelta
1112
import functools
1213

@@ -336,6 +337,34 @@ def dim_summary(obj):
336337
return u', '.join(elements)
337338

338339

340+
@contextlib.contextmanager
341+
def set_numpy_options(*args, **kwargs):
342+
original = np.get_printoptions()
343+
np.set_printoptions(*args, **kwargs)
344+
yield
345+
np.set_printoptions(**original)
346+
347+
348+
def short_array_repr(array):
349+
array = np.asarray(array)
350+
# default to lower precision so a full (abbreviated) line can fit on
351+
# one line with the default display_width
352+
options = {
353+
'precision': 6,
354+
'linewidth': OPTIONS['display_width'],
355+
'threshold': 200,
356+
}
357+
if array.ndim < 3:
358+
edgeitems = 3
359+
elif array.ndim == 3:
360+
edgeitems = 2
361+
else:
362+
edgeitems = 1
363+
options['edgeitems'] = edgeitems
364+
with set_numpy_options(**options):
365+
return repr(array)
366+
367+
339368
def array_repr(arr):
340369
# used for DataArray, Variable and IndexVariable
341370
if hasattr(arr, 'name') and arr.name is not None:
@@ -349,7 +378,7 @@ def array_repr(arr):
349378
if isinstance(getattr(arr, 'variable', arr)._data, dask_array_type):
350379
summary.append(repr(arr.data))
351380
elif arr._in_memory or arr.size < 1e5:
352-
summary.append(repr(arr.values))
381+
summary.append(short_array_repr(arr.values))
353382
else:
354383
summary.append(u'[%s values with dtype=%s]' % (arr.size, arr.dtype))
355384

xarray/test/test_formatting.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,26 @@ def test_format_timestamp_out_of_bounds(self):
130130
expected = '2300-12-01'
131131
result = formatting.format_timestamp(date)
132132
self.assertEqual(result, expected)
133+
134+
135+
def test_set_numpy_options():
136+
original_options = np.get_printoptions()
137+
with formatting.set_numpy_options(threshold=10):
138+
assert len(repr(np.arange(500))) < 200
139+
# original options are restored
140+
assert np.get_printoptions() == original_options
141+
142+
143+
def test_short_array_repr():
144+
cases = [
145+
np.random.randn(500),
146+
np.random.randn(20, 20),
147+
np.random.randn(5, 10, 15),
148+
np.random.randn(5, 10, 15, 3),
149+
]
150+
# number of lines:
151+
# for default numpy repr: 167, 140, 254, 248
152+
# for short_array_repr: 1, 7, 24, 19
153+
for array in cases:
154+
num_lines = formatting.short_array_repr(array).count('\n') + 1
155+
assert num_lines < 30

0 commit comments

Comments
 (0)