Skip to content

Commit 025724e

Browse files
committed
changed according to comments
1 parent f92bb0d commit 025724e

File tree

4 files changed

+58
-54
lines changed

4 files changed

+58
-54
lines changed

doc/source/whatsnew/v0.24.0.txt

+3-6
Original file line numberDiff line numberDiff line change
@@ -176,14 +176,11 @@ understand the structure of the ``MultiIndex``. (:issue:`13480`):
176176

177177
.. ipython:: python
178178

179-
index1=range(1000)
180-
index2 = pd.Index(['a'] * 500 + ['abc'] * 500)
181-
pd.MultiIndex.from_arrays([index1, index2])
179+
pd.MultiIndex.from_product([['a', 'abc'], range(500)])
182180

183-
For number of rows smaller than :attr:`options.display.max_seq_items`, all
184-
values will be shown (default: 100 items). Horizontally, the output will
181+
If the number of rows is smaller than :attr:`options.display.max_seq_items`,
182+
all values will be shown (default: 100 items). Horizontally, the output will
185183
truncate, if it's longer than :attr:`options.display.width` (default: 80 characters).
186-
This solves the problem with outputting large MultiIndex instances to the console.
187184

188185

189186
.. _whatsnew_0240.enhancements.other:

pandas/core/indexes/multi.py

+1-24
Original file line numberDiff line numberDiff line change
@@ -636,30 +636,7 @@ def _format_data(self, name=None):
636636
Return the formatted data as a unicode string
637637
"""
638638
return format_object_summary(self, self._formatter_func,
639-
name=name, is_multi=True)
640-
641-
def __unicode__(self):
642-
"""
643-
Return a string representation for this MultiIndex.
644-
645-
Invoked by unicode(df) in py2 only. Yields a Unicode String in both
646-
py2/py3.
647-
"""
648-
klass = self.__class__.__name__
649-
data = self._format_data()
650-
attrs = self._format_attrs()
651-
space = self._format_space()
652-
653-
prepr = (u(",%s") %
654-
space).join(u("%s=%s") % (k, v) for k, v in attrs)
655-
656-
# no data provided, just attributes
657-
if data is None:
658-
data = ''
659-
660-
res = u("%s(%s%s)") % (klass, data, prepr)
661-
662-
return res
639+
name=name, line_break_each_value=True)
663640

664641
def __len__(self):
665642
return len(self.labels[0])

pandas/io/formats/printing.py

+47-24
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ class TableSchemaFormatter(BaseFormatter):
269269

270270

271271
def format_object_summary(obj, formatter, is_justify=True,
272-
name=None, is_multi=False):
272+
name=None, line_break_each_value=False):
273273
"""
274274
Return the formatted obj as a unicode string
275275
@@ -283,8 +283,10 @@ def format_object_summary(obj, formatter, is_justify=True,
283283
should justify the display
284284
name : name, optional
285285
defaults to the class name of the obj
286-
is_multi : bool, default False
287-
Is ``obj`` a :class:`MultiIndex` or not
286+
line_break_each_value : bool, default False
287+
If True, inserts a line break for each value of ``obj``.
288+
If False, only break lines when the a line of values gets wider
289+
than the display width
288290
289291
Returns
290292
-------
@@ -304,7 +306,7 @@ def format_object_summary(obj, formatter, is_justify=True,
304306
space2 = "\n%s" % (' ' * (len(name) + 2))
305307

306308
n = len(obj)
307-
sep = ',' if not is_multi else (',\n ' + ' ' * len(name))
309+
sep = ',' if not line_break_each_value else (',\n ' + ' ' * len(name))
308310
max_seq_items = get_option('display.max_seq_items') or n
309311

310312
# are we a truncated display
@@ -330,10 +332,10 @@ def best_len(values):
330332

331333
if n == 0:
332334
summary = '[], '
333-
elif n == 1 and not is_multi:
335+
elif n == 1 and not line_break_each_value:
334336
first = formatter(obj[0])
335337
summary = '[%s], ' % first
336-
elif n == 2 and not is_multi:
338+
elif n == 2 and not line_break_each_value:
337339
first = formatter(obj[0])
338340
last = formatter(obj[-1])
339341
summary = '[%s, %s], ' % (first, last)
@@ -349,9 +351,15 @@ def best_len(values):
349351

350352
# adjust all values to max length if needed
351353
if is_justify:
352-
head, tail = _justify(head, tail, display_width, best_len,
353-
is_truncated, is_multi)
354-
if is_multi:
354+
if line_break_each_value:
355+
head, tail = _justify(head, tail)
356+
elif (is_truncated or not (len(', '.join(head)) < display_width and
357+
len(', '.join(tail)) < display_width)):
358+
max_length = max(best_len(head), best_len(tail))
359+
head = [x.rjust(max_length) for x in head]
360+
tail = [x.rjust(max_length) for x in tail]
361+
362+
if line_break_each_value:
355363
max_space = display_width - len(space2)
356364
item = tail[0]
357365
for i in reversed(range(1, len(item) + 1)):
@@ -384,7 +392,7 @@ def best_len(values):
384392
summary += line
385393
summary += '],'
386394

387-
if len(summary) > (display_width) or is_multi:
395+
if len(summary) > (display_width) or line_break_each_value:
388396
summary += space1
389397
else: # one row
390398
summary += ' '
@@ -395,23 +403,38 @@ def best_len(values):
395403
return summary
396404

397405

398-
def _justify(head, tail, display_width, best_len,
399-
is_truncated=False, is_multi=False):
406+
def _justify(head, tail):
400407
"""
401-
Justify each item in head and tail, so they align properly.
408+
Justify each item in each list-like in head and tail, so each item
409+
right-aligns when the two list-likes are stacked vertically.
410+
411+
Parameters
412+
----------
413+
head : list-like of list-likes of strings
414+
tail : list-like of list-likes of strings
415+
416+
Returns
417+
-------
418+
head : list of tuples of strings
419+
tail : list of tuples of strings
420+
421+
Examples
422+
--------
423+
>>> _justify([['a', 'b']], [['abc', 'abcd']])
424+
([(' a', ' b')], [('abc', 'abcd')])
402425
"""
403-
if is_multi:
404-
max_length = _max_level_item_length(head + tail)
405-
head = [tuple(x.rjust(max_len) for x, max_len in zip(seq, max_length))
406-
for seq in head]
407-
tail = [tuple(x.rjust(max_len) for x, max_len in zip(seq, max_length))
408-
for seq in tail]
409-
elif (is_truncated or not (len(', '.join(head)) < display_width and
410-
len(', '.join(tail)) < display_width)):
411-
max_length = max(best_len(head), best_len(tail))
412-
head = [x.rjust(max_length) for x in head]
413-
tail = [x.rjust(max_length) for x in tail]
426+
seq = head + tail # type: List[str]
427+
# For each position for the sequences in ``seq``, find the largest length.
428+
max_length = [0] * len(seq[0]) # type: List[int]
429+
for inner_seq in seq:
430+
length = [len(item) for item in inner_seq]
431+
max_length = [max(x, y) for x, y in zip(max_length, length)]
414432

433+
# justify each item in each list-like in head and tail using max_length
434+
head = [tuple(x.rjust(max_len) for x, max_len in zip(seq, max_length))
435+
for seq in head]
436+
tail = [tuple(x.rjust(max_len) for x, max_len in zip(seq, max_length))
437+
for seq in tail]
415438
return head, tail
416439

417440

pandas/tests/indexes/multi/test_format.py

+7
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@ def test_repr_with_unicode_data():
5959
assert "\\u" not in repr(index) # we don't want unicode-escaped
6060

6161

62+
def test_repr_roundtrip_raises():
63+
mi = MultiIndex.from_product([list('ab'), range(3)],
64+
names=['first', 'second'])
65+
with pytest.raises(TypeError):
66+
eval(repr(mi))
67+
68+
6269
def test_unicode_string_with_unicode():
6370
d = {"a": [u("\u05d0"), 2, 3], "b": [4, 5, 6], "c": [7, 8, 9]}
6471
idx = pd.DataFrame(d).set_index(["a", "b"]).index

0 commit comments

Comments
 (0)