Skip to content

Commit f53d38b

Browse files
BUG: show series length in repr when truncated (GH15962) (pandas-dev#15974)
1 parent cd1031f commit f53d38b

File tree

6 files changed

+51
-40
lines changed

6 files changed

+51
-40
lines changed

doc/source/whatsnew/v0.20.0.txt

+3
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,8 @@ Other Enhancements
518518
- :method:`~MultiIndex.remove_unused_levels` has been added to facilitate :ref:`removing unused levels <advanced.shown_levels>`. (:issue:`15694`)
519519
- ``pd.read_csv()`` will now raise a ``ParserError`` error whenever any parsing error occurs (:issue:`15913`, :issue:`15925`)
520520
- ``pd.read_csv()`` now supports the ``error_bad_lines`` and ``warn_bad_lines`` arguments for the Python parser (:issue:`15925`)
521+
- The ``display.show_dimensions`` option can now also be used to specify
522+
whether the length of a ``Series`` should be shown in its repr (:issue:`7117`).
521523
- ``parallel_coordinates()`` has gained a ``sort_labels`` keyword arg that sorts class labels and the colours assigned to them (:issue:`15908`)
522524

523525

@@ -1560,6 +1562,7 @@ I/O
15601562
- Bug in ``pd.read_hdf()`` passing a ``Timestamp`` to the ``where`` parameter with a non date column (:issue:`15492`)
15611563
- Bug in ``DataFrame.to_stata()`` and ``StataWriter`` which produces incorrectly formatted files to be produced for some locales (:issue:`13856`)
15621564
- Bug in ``StataReader`` and ``StataWriter`` which allows invalid encodings (:issue:`15723`)
1565+
- Bug in the ``Series`` repr not showing the length when the output was truncated (:issue:`15962`).
15631566

15641567
Plotting
15651568
^^^^^^^^

pandas/core/series.py

+12-28
Original file line numberDiff line numberDiff line change
@@ -980,9 +980,10 @@ def __unicode__(self):
980980
width, height = get_terminal_size()
981981
max_rows = (height if get_option("display.max_rows") == 0 else
982982
get_option("display.max_rows"))
983+
show_dimensions = get_option("display.show_dimensions")
983984

984985
self.to_string(buf=buf, name=self.name, dtype=self.dtype,
985-
max_rows=max_rows)
986+
max_rows=max_rows, length=show_dimensions)
986987
result = buf.getvalue()
987988

988989
return result
@@ -1021,44 +1022,27 @@ def to_string(self, buf=None, na_rep='NaN', float_format=None, header=True,
10211022
formatted : string (if not buffer passed)
10221023
"""
10231024

1024-
the_repr = self._get_repr(float_format=float_format, na_rep=na_rep,
1025-
header=header, index=index, length=length,
1026-
dtype=dtype, name=name, max_rows=max_rows)
1027-
1028-
# catch contract violations
1029-
if not isinstance(the_repr, compat.text_type):
1030-
raise AssertionError("result must be of type unicode, type"
1031-
" of result is {0!r}"
1032-
"".format(the_repr.__class__.__name__))
1033-
1034-
if buf is None:
1035-
return the_repr
1036-
else:
1037-
try:
1038-
buf.write(the_repr)
1039-
except AttributeError:
1040-
with open(buf, 'w') as f:
1041-
f.write(the_repr)
1042-
1043-
def _get_repr(self, name=False, header=True, index=True, length=True,
1044-
dtype=True, na_rep='NaN', float_format=None, max_rows=None):
1045-
"""
1046-
1047-
Internal function, should always return unicode string
1048-
"""
10491025
formatter = fmt.SeriesFormatter(self, name=name, length=length,
10501026
header=header, index=index,
10511027
dtype=dtype, na_rep=na_rep,
10521028
float_format=float_format,
10531029
max_rows=max_rows)
10541030
result = formatter.to_string()
10551031

1056-
# TODO: following check prob. not neces.
1032+
# catch contract violations
10571033
if not isinstance(result, compat.text_type):
10581034
raise AssertionError("result must be of type unicode, type"
10591035
" of result is {0!r}"
10601036
"".format(result.__class__.__name__))
1061-
return result
1037+
1038+
if buf is None:
1039+
return result
1040+
else:
1041+
try:
1042+
buf.write(result)
1043+
except AttributeError:
1044+
with open(buf, 'w') as f:
1045+
f.write(result)
10621046

10631047
def __iter__(self):
10641048
""" provide iteration over the values of the Series

pandas/io/formats/format.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,8 @@ def _get_footer(self):
199199
escape_chars=('\t', '\r', '\n'))
200200
footer += ("Name: %s" % series_name) if name is not None else ""
201201

202-
if self.length:
202+
if (self.length is True or
203+
(self.length == 'truncate' and self.truncate_v)):
203204
if footer:
204205
footer += ', '
205206
footer += 'Length: %d' % len(self.series)

pandas/tests/io/formats/test_format.py

+27-6
Original file line numberDiff line numberDiff line change
@@ -1770,12 +1770,14 @@ def test_east_asian_unicode_series(self):
17701770
name=u'おおおおおおお')
17711771

17721772
expected = (u"0 あ\n ... \n"
1773-
u"3 ええええ\nName: おおおおおおお, dtype: object")
1773+
u"3 ええええ\n"
1774+
u"Name: おおおおおおお, Length: 4, dtype: object")
17741775
self.assertEqual(_rep(s), expected)
17751776

17761777
s.index = [u'ああ', u'いいいい', u'う', u'えええ']
17771778
expected = (u"ああ あ\n ... \n"
1778-
u"えええ ええええ\nName: おおおおおおお, dtype: object")
1779+
u"えええ ええええ\n"
1780+
u"Name: おおおおおおお, Length: 4, dtype: object")
17791781
self.assertEqual(_rep(s), expected)
17801782

17811783
# Emable Unicode option -----------------------------------------
@@ -1846,14 +1848,15 @@ def test_east_asian_unicode_series(self):
18461848
s = Series([u'あ', u'いい', u'ううう', u'ええええ'],
18471849
name=u'おおおおおおお')
18481850
expected = (u"0 あ\n ... \n"
1849-
u"3 ええええ\nName: おおおおおおお, dtype: object")
1851+
u"3 ええええ\n"
1852+
u"Name: おおおおおおお, Length: 4, dtype: object")
18501853
self.assertEqual(_rep(s), expected)
18511854

18521855
s.index = [u'ああ', u'いいいい', u'う', u'えええ']
18531856
expected = (u"ああ あ\n"
18541857
u" ... \n"
18551858
u"えええ ええええ\n"
1856-
u"Name: おおおおおおお, dtype: object")
1859+
u"Name: おおおおおおお, Length: 4, dtype: object")
18571860
self.assertEqual(_rep(s), expected)
18581861

18591862
# ambiguous unicode
@@ -2021,7 +2024,8 @@ def test_max_multi_index_display(self):
20212024
# Make sure #8532 is fixed
20222025
def test_consistent_format(self):
20232026
s = pd.Series([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9999, 1, 1] * 10)
2024-
with option_context("display.max_rows", 10):
2027+
with option_context("display.max_rows", 10,
2028+
"display.show_dimensions", False):
20252029
res = repr(s)
20262030
exp = ('0 1.0000\n1 1.0000\n2 1.0000\n3 '
20272031
'1.0000\n4 1.0000\n ... \n125 '
@@ -2040,7 +2044,8 @@ def chck_ncols(self, s):
20402044

20412045
def test_format_explicit(self):
20422046
test_sers = gen_series_formatting()
2043-
with option_context("display.max_rows", 4):
2047+
with option_context("display.max_rows", 4,
2048+
"display.show_dimensions", False):
20442049
res = repr(test_sers['onel'])
20452050
exp = '0 a\n1 a\n ..\n98 a\n99 a\ndtype: object'
20462051
self.assertEqual(exp, res)
@@ -2087,6 +2092,22 @@ def getndots(s):
20872092
strrepr = repr(s).replace('\n', '')
20882093
self.assertEqual(getndots(strrepr), 3)
20892094

2095+
def test_show_dimensions(self):
2096+
# gh-7117
2097+
s = Series(range(5))
2098+
2099+
assert 'Length' not in repr(s)
2100+
2101+
with option_context("display.max_rows", 4):
2102+
assert 'Length' in repr(s)
2103+
2104+
with option_context("display.show_dimensions", True):
2105+
assert 'Length' in repr(s)
2106+
2107+
with option_context("display.max_rows", 4,
2108+
"display.show_dimensions", False):
2109+
assert 'Length' not in repr(s)
2110+
20902111
def test_to_string_name(self):
20912112
s = Series(range(100), dtype='int64')
20922113
s.name = 'myser'

pandas/tests/sparse/test_format.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def test_sparse_max_row(self):
3333
# GH 10560
3434
result = repr(s)
3535
exp = ("0 1.0\n ... \n4 NaN\n"
36-
"dtype: float64\nBlockIndex\n"
36+
"Length: 5, dtype: float64\nBlockIndex\n"
3737
"Block locations: array([0, 3]{0})\n"
3838
"Block lengths: array([1, 1]{0})".format(dfm))
3939
self.assertEqual(result, exp)
@@ -52,7 +52,8 @@ def test_sparse_mi_max_row(self):
5252
"Block lengths: array([1, 1]{0})".format(dfm))
5353
self.assertEqual(result, exp)
5454

55-
with option_context("display.max_rows", 3):
55+
with option_context("display.max_rows", 3,
56+
"display.show_dimensions", False):
5657
# GH 13144
5758
result = repr(s)
5859
exp = ("A 0 1.0\n ... \nC 2 NaN\n"
@@ -77,7 +78,7 @@ def test_sparse_bool(self):
7778
with option_context("display.max_rows", 3):
7879
result = repr(s)
7980
exp = ("0 True\n ... \n5 False\n"
80-
"dtype: bool\nBlockIndex\n"
81+
"Length: 6, dtype: bool\nBlockIndex\n"
8182
"Block locations: array([0, 3]{0})\n"
8283
"Block lengths: array([1, 1]{0})".format(dtype))
8384
self.assertEqual(result, exp)
@@ -94,7 +95,8 @@ def test_sparse_int(self):
9495
"Block lengths: array([1, 1]{0})".format(dtype))
9596
self.assertEqual(result, exp)
9697

97-
with option_context("display.max_rows", 3):
98+
with option_context("display.max_rows", 3,
99+
"display.show_dimensions", False):
98100
result = repr(s)
99101
exp = ("0 0\n ..\n5 0\n"
100102
"dtype: int64\nBlockIndex\n"

pandas/tests/test_categorical.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2088,7 +2088,7 @@ def test_repr(self):
20882088

20892089
a = pd.Series(pd.Categorical(["a", "b"] * 25))
20902090
exp = u("0 a\n1 b\n" + " ..\n" + "48 a\n49 b\n" +
2091-
"dtype: category\nCategories (2, object): [a, b]")
2091+
"Length: 50, dtype: category\nCategories (2, object): [a, b]")
20922092
with option_context("display.max_rows", 5):
20932093
self.assertEqual(exp, repr(a))
20942094

0 commit comments

Comments
 (0)