Skip to content

BUG: Fix Index.__repr__ when display.max_seq_items = 1 #38443

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Dec 28, 2020
3 changes: 1 addition & 2 deletions doc/source/whatsnew/v1.3.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,6 @@ Performance improvements
Bug fixes
~~~~~~~~~

-
-

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you undo this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Have reverted the changes.

Categorical
^^^^^^^^^^^
Expand Down Expand Up @@ -217,6 +215,7 @@ MultiIndex
I/O
^^^

- Bug in :meth:`Index.__repr__` when ``display.max_seq_items=1`` (:issue:`38415`)
- Bug in :func:`read_csv` interpreting ``NA`` value as comment, when ``NA`` does contain the comment string fixed for ``engine="python"`` (:issue:`34002`)
- Bug in :func:`read_csv` raising ``IndexError`` with multiple header columns and ``index_col`` specified when file has no data rows (:issue:`38292`)
- Bug in :func:`read_csv` not accepting ``usecols`` with different length than ``names`` for ``engine="python"`` (:issue:`16469`)
Expand Down
6 changes: 5 additions & 1 deletion pandas/io/formats/printing.py
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,11 @@ def best_len(values: List[str]) -> int:
summary = f"[{first}, {last}]{close}"
else:

if n > max_seq_items:
if max_seq_items == 1:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you also cover in a test the max_seq_items == 0 case (I think we have this but maybe not). Also pls confirm that we have a test for n == max_seq_items.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we don't have a test for n == max_seq_items. Will cover these in my tests.

Just wanted to confirm that this is the relevant location for adding these?

def test_repr(self, idx):
result = idx[:1].__repr__()
expected = """\
MultiIndex([('foo', 'one')],
names=['first', 'second'])"""
assert result == expected
result = idx.__repr__()
expected = """\
MultiIndex([('foo', 'one'),
('foo', 'two'),
('bar', 'one'),
('baz', 'two'),
('qux', 'one'),
('qux', 'two')],
names=['first', 'second'])"""
assert result == expected
with pd.option_context("display.max_seq_items", 5):
result = idx.__repr__()
expected = """\
MultiIndex([('foo', 'one'),
('foo', 'two'),
...
('qux', 'one'),
('qux', 'two')],
names=['first', 'second'], length=6)"""
assert result == expected

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah there plus some generic Index ones (look in pandas/tests/indexes/); you may have to grep around a bit

e.g.

~/pandas-dev$ grep -r max_seq_items pandas/tests/
pandas/tests/io/formats/test_format.py:        with option_context("display.max_seq_items", 2000):
pandas/tests/io/formats/test_format.py:        with option_context("display.max_seq_items", 5):
pandas/tests/groupby/test_groupby.py:    "max_seq_items, expected",
pandas/tests/groupby/test_groupby.py:def test_groups_repr_truncates(max_seq_items, expected):
pandas/tests/groupby/test_groupby.py:    with pd.option_context("display.max_seq_items", max_seq_items):
pandas/tests/indexes/multi/test_formats.py:    with pd.option_context("display.max_seq_items", None):
pandas/tests/indexes/multi/test_formats.py:        with pd.option_context("display.max_seq_items", 5):
pandas/tests/indexes/common.py:        with pd.option_context("display.max_seq_items", None):
pandas/tests/indexes/base_class/test_formats.py:        with cf.option_context("display.max_seq_items", 10):

i think pandas/tests/indexes/base_class/test_formats.py: with cf.option_context("display.max_seq_items", 10):
has a number of tests as well

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we have a case of max_seq_items==0 ? (I think this is a valid value), < 0 is restricted i am pretty sure?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes we do. Max_seq_items ==0 implies unlimited if I'm not mistaken

# If max_seq_items=1 show only last element
head = []
tail = [formatter(x) for x in obj[-1:]]
elif n > max_seq_items:
n = min(max_seq_items // 2, 10)
head = [formatter(x) for x in obj[:n]]
tail = [formatter(x) for x in obj[-n:]]
Expand Down
22 changes: 22 additions & 0 deletions pandas/tests/indexes/multi/test_formats.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,28 @@ def test_repr(self, idx):
names=['first', 'second'], length=6)"""
assert result == expected

# display.max_seq_items == n
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prob better to make a new test as easier to see / run

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. Moved this to it's own test case

with pd.option_context("display.max_seq_items", 6):
result = idx.__repr__()
expected = """\
MultiIndex([('foo', 'one'),
('foo', 'two'),
('bar', 'one'),
('baz', 'two'),
('qux', 'one'),
('qux', 'two')],
names=['first', 'second'])"""
assert result == expected

# display.max_seq_items == 1
with pd.option_context("display.max_seq_items", 1):
result = idx.__repr__()
expected = """\
MultiIndex([...
('qux', 'two')],
names=['first', ...], length=6)"""
assert result == expected

def test_rjust(self, narrow_multi_index):
mi = narrow_multi_index
result = mi[:1].__repr__()
Expand Down