Skip to content

Commit 26421eb

Browse files
committed
Fix undesired UX behavior of DataFrame output in IPython Notebook pandas-dev#10231
1 parent 676cb95 commit 26421eb

File tree

4 files changed

+51
-15
lines changed

4 files changed

+51
-15
lines changed

doc/source/whatsnew/v0.16.2.txt

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ New features
2525
Other enhancements
2626
^^^^^^^^^^^^^^^^^^
2727

28+
- Removed duplicate scroll bars in DataFrame HTML representation. In pandas internal, large DataFrame's output will be wrapped with vertical and horizontal scroll bars. It is unnecessary because IPython has "toggle output scrolling" feature. In IPython below v3.0 the output is still wrapped with horizontal scroll bar because the horizontal scroll bar is not included (yet) in "toogle output scrolling" feature. In IPython v3.0 or later it is included so the output's scrollability all handled by IPython. (:issue:`10231`)
29+
2830
.. _whatsnew_0162.api:
2931

3032
Backwards incompatible API changes

pandas/core/format.py

+28-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# -*- coding: utf-8 -*-
22
from __future__ import print_function
3+
from distutils.version import LooseVersion
34
# pylint: disable=W0141
45

56
import sys
@@ -692,13 +693,20 @@ def _format_col(self, i):
692693
space=self.col_space
693694
)
694695

695-
def to_html(self, classes=None):
696+
def to_html(self, classes=None, notebook=False):
696697
"""
697698
Render a DataFrame to a html table.
699+
700+
Parameters
701+
----------
702+
notebook : {True, False}, optional, default False
703+
Whether the generated HTML is for IPython Notebook.
704+
698705
"""
699706
html_renderer = HTMLFormatter(self, classes=classes,
700707
max_rows=self.max_rows,
701-
max_cols=self.max_cols)
708+
max_cols=self.max_cols,
709+
notebook=notebook)
702710
if hasattr(self.buf, 'write'):
703711
html_renderer.write_result(self.buf)
704712
elif isinstance(self.buf, compat.string_types):
@@ -808,7 +816,8 @@ class HTMLFormatter(TableFormatter):
808816

809817
indent_delta = 2
810818

811-
def __init__(self, formatter, classes=None, max_rows=None, max_cols=None):
819+
def __init__(self, formatter, classes=None, max_rows=None, max_cols=None,
820+
notebook=False):
812821
self.fmt = formatter
813822
self.classes = classes
814823

@@ -823,6 +832,7 @@ def __init__(self, formatter, classes=None, max_rows=None, max_cols=None):
823832
self.show_dimensions = self.fmt.show_dimensions
824833
self.is_truncated = (self.max_rows < len(self.fmt.frame) or
825834
self.max_cols < len(self.fmt.columns))
835+
self.notebook = notebook
826836

827837
def write(self, s, indent=0):
828838
rs = com.pprint_thing(s)
@@ -890,6 +900,17 @@ def write_result(self, buf):
890900
'not %s') % type(self.classes))
891901
_classes.extend(self.classes)
892902

903+
if self.notebook:
904+
div_style = ''
905+
try:
906+
import IPython
907+
if IPython.__version__ < LooseVersion('3.0.0'):
908+
div_style = ' style="max-width:1500px;overflow:auto;"'
909+
except ImportError:
910+
pass
911+
912+
self.write('<div{0}>'.format(div_style))
913+
893914
self.write('<table border="1" class="%s">' % ' '.join(_classes),
894915
indent)
895916

@@ -902,6 +923,10 @@ def write_result(self, buf):
902923
by = chr(215) if compat.PY3 else unichr(215) # ×
903924
self.write(u('<p>%d rows %s %d columns</p>') %
904925
(len(frame), by, len(frame.columns)))
926+
927+
if self.notebook:
928+
self.write('</div>')
929+
905930
_put_lines(buf, self.elements)
906931

907932
def _write_header(self, indent):

pandas/core/frame.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -538,10 +538,9 @@ def _repr_html_(self):
538538
max_cols = get_option("display.max_columns")
539539
show_dimensions = get_option("display.show_dimensions")
540540

541-
return ('<div style="max-height:1000px;'
542-
'max-width:1500px;overflow:auto;">\n' +
543-
self.to_html(max_rows=max_rows, max_cols=max_cols,
544-
show_dimensions=show_dimensions) + '\n</div>')
541+
return self.to_html(max_rows=max_rows, max_cols=max_cols,
542+
show_dimensions=show_dimensions,
543+
notebook=True)
545544
else:
546545
return None
547546

@@ -1349,7 +1348,8 @@ def to_html(self, buf=None, columns=None, col_space=None, colSpace=None,
13491348
header=True, index=True, na_rep='NaN', formatters=None,
13501349
float_format=None, sparsify=None, index_names=True,
13511350
justify=None, bold_rows=True, classes=None, escape=True,
1352-
max_rows=None, max_cols=None, show_dimensions=False):
1351+
max_rows=None, max_cols=None, show_dimensions=False,
1352+
notebook=False):
13531353
"""
13541354
Render a DataFrame as an HTML table.
13551355
@@ -1388,7 +1388,7 @@ def to_html(self, buf=None, columns=None, col_space=None, colSpace=None,
13881388
max_rows=max_rows,
13891389
max_cols=max_cols,
13901390
show_dimensions=show_dimensions)
1391-
formatter.to_html(classes=classes)
1391+
formatter.to_html(classes=classes, notebook=notebook)
13921392

13931393
if buf is None:
13941394
return formatter.buf.getvalue()

pandas/tests/test_format.py

+15-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# -*- coding: utf-8 -*-
22
from __future__ import print_function
3+
from distutils.version import LooseVersion
34
import re
45

56
from pandas.compat import range, zip, lrange, StringIO, PY3, lzip, u
@@ -14,6 +15,14 @@
1415
from numpy.random import randn
1516
import numpy as np
1617

18+
div_style = ''
19+
try:
20+
import IPython
21+
if IPython.__version__ < LooseVersion('3.0.0'):
22+
div_style = ' style="max-width:1500px;overflow:auto;"'
23+
except ImportError:
24+
pass
25+
1726
from pandas import DataFrame, Series, Index, Timestamp, MultiIndex, date_range, NaT
1827

1928
import pandas.core.format as fmt
@@ -892,7 +901,7 @@ def test_to_html_truncate(self):
892901
fmt.set_option('display.max_columns',4)
893902
result = df._repr_html_()
894903
expected = '''\
895-
<div style="max-height:1000px;max-width:1500px;overflow:auto;">
904+
<div{0}>
896905
<table border="1" class="dataframe">
897906
<thead>
898907
<tr style="text-align: right;">
@@ -980,7 +989,7 @@ def test_to_html_truncate(self):
980989
</tbody>
981990
</table>
982991
<p>20 rows × 20 columns</p>
983-
</div>'''
992+
</div>'''.format(div_style)
984993
if sys.version_info[0] < 3:
985994
expected = expected.decode('utf-8')
986995
self.assertEqual(result, expected)
@@ -993,7 +1002,7 @@ def test_to_html_truncate_multi_index(self):
9931002
fmt.set_option('display.max_columns',7)
9941003
result = df._repr_html_()
9951004
expected = '''\
996-
<div style="max-height:1000px;max-width:1500px;overflow:auto;">
1005+
<div{0}>
9971006
<table border="1" class="dataframe">
9981007
<thead>
9991008
<tr>
@@ -1096,7 +1105,7 @@ def test_to_html_truncate_multi_index(self):
10961105
</tbody>
10971106
</table>
10981107
<p>8 rows × 8 columns</p>
1099-
</div>'''
1108+
</div>'''.format(div_style)
11001109
if sys.version_info[0] < 3:
11011110
expected = expected.decode('utf-8')
11021111
self.assertEqual(result, expected)
@@ -1110,7 +1119,7 @@ def test_to_html_truncate_multi_index_sparse_off(self):
11101119
fmt.set_option('display.multi_sparse',False)
11111120
result = df._repr_html_()
11121121
expected = '''\
1113-
<div style="max-height:1000px;max-width:1500px;overflow:auto;">
1122+
<div{0}>
11141123
<table border="1" class="dataframe">
11151124
<thead>
11161125
<tr>
@@ -1206,7 +1215,7 @@ def test_to_html_truncate_multi_index_sparse_off(self):
12061215
</tbody>
12071216
</table>
12081217
<p>8 rows × 8 columns</p>
1209-
</div>'''
1218+
</div>'''.format(div_style)
12101219
if sys.version_info[0] < 3:
12111220
expected = expected.decode('utf-8')
12121221
self.assertEqual(result, expected)

0 commit comments

Comments
 (0)