Skip to content

FIX printing index with display.max_seq_items=None (GH10182) #10183

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
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/source/whatsnew/v0.16.2.txt
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ Bug Fixes
- Bug in ``Timestamp``'s' ``microsecond``, ``quarter``, ``dayofyear``, ``week`` and ``daysinmonth`` properties return ``np.int`` type, not built-in ``int``. (:issue:`10050`)
- Bug in ``NaT`` raises ``AttributeError`` when accessing to ``daysinmonth``, ``dayofweek`` properties. (:issue:`10096`)

- Bug in Index repr when using the ``max_seq_items=None`` setting (:issue:`10182`).

- Bug in getting timezone data with ``dateutil`` on various platforms ( :issue:`9059`, :issue:`8639`, :issue:`9663`, :issue:`10121`)
- Bug in display datetimes with mixed frequencies uniformly; display 'ms' datetimes to the proper precision. (:issue:`10170`)
Expand Down
14 changes: 14 additions & 0 deletions pandas/core/categorical.py
Original file line number Diff line number Diff line change
Expand Up @@ -1599,6 +1599,20 @@ def describe(self):

return result

def repeat(self, repeats):
"""
Repeat elements of a Categorical.

See also
--------
numpy.ndarray.repeat

"""
codes = self._codes.repeat(repeats)
return Categorical(values=codes, categories=self.categories,
ordered=self.ordered, name=self.name, fastpath=True)


##### The Series.cat accessor #####

class CategoricalAccessor(PandasDelegate):
Expand Down
6 changes: 3 additions & 3 deletions pandas/core/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ def _format_data(self):

n = len(self)
sep = ','
max_seq_items = get_option('display.max_seq_items')
max_seq_items = get_option('display.max_seq_items') or n
formatter = self._formatter_func

# do we want to justify (only do so for non-objects)
Expand Down Expand Up @@ -534,7 +534,7 @@ def _format_attrs(self):
attrs.append(('dtype',"'%s'" % self.dtype))
if self.name is not None:
attrs.append(('name',default_pprint(self.name)))
max_seq_items = get_option('display.max_seq_items')
max_seq_items = get_option('display.max_seq_items') or len(self)
if len(self) > max_seq_items:
attrs.append(('length',len(self)))
return attrs
Expand Down Expand Up @@ -2950,7 +2950,7 @@ def _format_attrs(self):
if self.name is not None:
attrs.append(('name',default_pprint(self.name)))
attrs.append(('dtype',"'%s'" % self.dtype))
max_seq_items = get_option('display.max_seq_items')
max_seq_items = get_option('display.max_seq_items') or len(self)
if len(self) > max_seq_items:
attrs.append(('length',len(self)))
return attrs
Expand Down
8 changes: 7 additions & 1 deletion pandas/tests/test_categorical.py
Original file line number Diff line number Diff line change
Expand Up @@ -2714,7 +2714,6 @@ def f():
df.append(df_wrong_categories)
self.assertRaises(ValueError, f)


def test_merge(self):
# GH 9426

Expand Down Expand Up @@ -2747,6 +2746,13 @@ def test_merge(self):
result = pd.merge(cleft, cright, how='left', left_on='b', right_on='c')
tm.assert_frame_equal(result, expected)

def test_repeat(self):
#GH10183
cat = pd.Categorical(["a","b"], categories=["a","b"])
exp = pd.Categorical(["a", "a", "b", "b"], categories=["a","b"])
res = cat.repeat(2)
self.assert_categorical_equal(res, exp)

def test_na_actions(self):

cat = pd.Categorical([1,2,3,np.nan], categories=[1,2,3])
Expand Down
16 changes: 16 additions & 0 deletions pandas/tests/test_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,14 @@ def test_str(self):
self.assertTrue("'foo'" in str(idx))
self.assertTrue(idx.__class__.__name__ in str(idx))

def test_repr_max_seq_item_setting(self):
Copy link
Contributor

Choose a reason for hiding this comment

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

move this to the Base class which tests for all sub-classes

Copy link
Member Author

Choose a reason for hiding this comment

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

this is already in the Base class

Copy link
Contributor

Choose a reason for hiding this comment

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

ahh, you know what the function above it is not testing much test_str (that's what I was looking at). should be iterating over the self.indices rather than using .create_index().

Copy link
Member Author

Choose a reason for hiding this comment

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

I am not fully following the logic of the test set up.

  • on the one hand, you have the self.indices -> so iterating over these will run this test for all the different index types
  • but create_index is also redefined in each subclass of Base, so in this way the test will also be run for the different index types

So it seems two ways to achieve a bit the same?

Copy link
Contributor

Choose a reason for hiding this comment

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

.indices has much more to test (and is customizable per sub-class), while .create_index is a single plain vanilla one. For the generic tests using .indices provides more coverage.

# GH10182
idx = self.create_index()
idx = idx.repeat(50)
with pd.option_context("display.max_seq_items", None):
repr(idx)
self.assertFalse('...' in str(idx))

def test_wrong_number_names(self):
def testit(ind):
ind.names = ["apple", "banana", "carrot"]
Expand Down Expand Up @@ -2857,6 +2865,14 @@ def test_get_indexer(self):
with self.assertRaisesRegexp(ValueError, 'different freq'):
idx.asfreq('D').get_indexer(idx)

def test_repeat(self):
# GH10183
idx = pd.period_range('2000-01-01', periods=3, freq='D')
res = idx.repeat(3)
Copy link
Contributor

Choose a reason for hiding this comment

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

move this as well to Base (you will have to model like other functions, e.g. iterate on self.indicies

Copy link
Member Author

Choose a reason for hiding this comment

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

problem here is that I explicitly wanted to test the freqstr as well (as this is what was actually not working)
(but I can have both, and put a generic one in Base as well)

exp = PeriodIndex(idx.values.repeat(3), freq='D')
self.assert_index_equal(res, exp)
self.assertEqual(res.freqstr, 'D')


class TestTimedeltaIndex(DatetimeLike, tm.TestCase):
_holder = TimedeltaIndex
Expand Down
11 changes: 11 additions & 0 deletions pandas/tseries/period.py
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,17 @@ def append(self, other):
for x in to_concat]
return Index(com._concat_compat(to_concat), name=name)

def repeat(self, n):
"""
Return a new Index of the values repeated n times.

See also
--------
numpy.ndarray.repeat
"""
# overwrites method from DatetimeIndexOpsMixin
return self._shallow_copy(self.values.repeat(n))

def __setstate__(self, state):
"""Necessary for making this object picklable"""

Expand Down