diff --git a/doc/source/release.rst b/doc/source/release.rst index c2cf938f6f806..b8e5b31bd873c 100644 --- a/doc/source/release.rst +++ b/doc/source/release.rst @@ -346,6 +346,8 @@ Improvements to existing features - Regression in the display of a MultiIndexed Series with ``display.max_rows`` is less than the length of the series (:issue:`7101`) - :meth:`~DataFrame.describe` now accepts an array of percentiles to include in the summary statistics (:issue:`4196`) +- allow option ``'truncate'`` for ``display.show_dimensions`` to only show the dimensions if the + frame is truncated (:issue:`6547`) .. _release.bug_fixes-0.14.0: diff --git a/doc/source/v0.14.0.txt b/doc/source/v0.14.0.txt index 9f050633a3b0d..4c099c627e6e5 100644 --- a/doc/source/v0.14.0.txt +++ b/doc/source/v0.14.0.txt @@ -204,6 +204,26 @@ API changes Display Changes ~~~~~~~~~~~~~~~ +- allow option ``'truncate'`` for ``display.show_dimensions`` to only show the dimensions if the + frame is truncated (:issue:`6547`). + + The default for ``display.show_dimensions`` will now be **truncate**! This is consistent with + how Series display length. + + .. ipython:: python + + dfd = pd.DataFrame(np.arange(25).reshape(-1,5), index=[0,1,2,3,4], columns=[0,1,2,3,4]) + + # show dimensions only if truncated + with pd.option_context('display.max_rows', 2, 'display.max_columns', 2, + 'display.show_dimensions', 'truncate'): + print(dfd) + + # show dimensions only if truncated + with pd.option_context('display.max_rows', 10, 'display.max_columns', 40, + 'display.show_dimensions', 'truncate'): + print(dfd) + - Regression in the display of a MultiIndexed Series with ``display.max_rows`` is less than the length of the series (:issue:`7101`) - Fixed a bug in the HTML repr of a truncated Series or DataFrame not showing the class name with the diff --git a/pandas/core/config_init.py b/pandas/core/config_init.py index 9533c0921e1e3..48665bc98ab6c 100644 --- a/pandas/core/config_init.py +++ b/pandas/core/config_init.py @@ -120,8 +120,10 @@ """ pc_show_dimensions_doc = """ -: boolean +: boolean or 'truncate' Whether to print out dimensions at the end of DataFrame repr. + If 'truncate' is specified, only print out the dimensions if the + frame is truncated (e.g. not display all rows and/or columns) """ pc_line_width_doc = """ @@ -247,7 +249,8 @@ def mpl_style_cb(key): cf.register_option('encoding', detect_console_encoding(), pc_encoding_doc, validator=is_text) cf.register_option('expand_frame_repr', True, pc_expand_repr_doc) - cf.register_option('show_dimensions', True, pc_show_dimensions_doc) + cf.register_option('show_dimensions', True, pc_show_dimensions_doc, + validator=is_one_of_factory([True, False, 'truncate'])) cf.register_option('chop_threshold', None, pc_chop_threshold_doc) cf.register_option('max_seq_items', 100, pc_max_seq_items) cf.register_option('mpl_style', None, pc_mpl_style_doc, diff --git a/pandas/core/format.py b/pandas/core/format.py index 0a4f65b6bf0e6..49e98fe9911c5 100644 --- a/pandas/core/format.py +++ b/pandas/core/format.py @@ -236,6 +236,12 @@ def _strlen(x): class TableFormatter(object): + is_truncated = False + show_dimensions = None + + @property + def should_show_dimensions(self): + return self.show_dimensions is True or (self.show_dimensions == 'truncate' and self.is_truncated) def _get_formatter(self, i): if isinstance(self.formatters, (list, tuple)): @@ -315,9 +321,9 @@ def _to_str_columns(self): _strlen = _strlen_func() cols_to_show = self.columns[:self.max_cols] - truncate_h = self.max_cols and (len(self.columns) > self.max_cols) - truncate_v = self.max_rows and (len(self.frame) > self.max_rows) - self.truncated_v = truncate_v + self.truncated_h = truncate_h = self.max_cols and (len(self.columns) > self.max_cols) + self.truncated_v = truncate_v = self.max_rows and (len(self.frame) > self.max_rows) + self.is_truncated = self.truncated_h or self.truncated_v if truncate_h: cols_to_show = self.columns[:self.max_cols] else: @@ -380,7 +386,7 @@ def to_string(self): self.buf.writelines(text) - if self.show_dimensions: + if self.should_show_dimensions: self.buf.write("\n\n[%d rows x %d columns]" % (len(frame), len(frame.columns))) @@ -634,6 +640,8 @@ def __init__(self, formatter, classes=None, max_rows=None, max_cols=None): self.max_rows = max_rows or len(self.fmt.frame) self.max_cols = max_cols or len(self.fmt.columns) + self.show_dimensions = self.fmt.show_dimensions + self.is_truncated = self.max_rows < len(self.fmt.frame) or self.max_cols < len(self.fmt.columns) def write(self, s, indent=0): rs = com.pprint_thing(s) @@ -709,7 +717,7 @@ def write_result(self, buf): indent = self._write_body(indent) self.write('', indent) - if self.fmt.show_dimensions: + if self.should_show_dimensions: by = chr(215) if compat.PY3 else unichr(215) # × self.write(u('

%d rows %s %d columns

') % (len(frame), by, len(frame.columns))) diff --git a/pandas/tests/test_format.py b/pandas/tests/test_format.py index 6e3893e5c0850..75bd03a71466e 100644 --- a/pandas/tests/test_format.py +++ b/pandas/tests/test_format.py @@ -1197,6 +1197,26 @@ def test_to_string_line_width(self): s = df.to_string(line_width=80) self.assertEqual(max(len(l) for l in s.split('\n')), 80) + def test_show_dimensions(self): + df = pd.DataFrame(123, lrange(10, 15), lrange(30)) + + with option_context('display.max_rows', 10, 'display.max_columns', 40, 'display.width', + 500, 'display.expand_frame_repr', 'info', 'display.show_dimensions', True): + self.assertTrue('5 rows' in str(df)) + self.assertTrue('5 rows' in df._repr_html_()) + with option_context('display.max_rows', 10, 'display.max_columns', 40, 'display.width', + 500, 'display.expand_frame_repr', 'info', 'display.show_dimensions', False): + self.assertFalse('5 rows' in str(df)) + self.assertFalse('5 rows' in df._repr_html_()) + with option_context('display.max_rows', 2, 'display.max_columns', 2, 'display.width', + 500, 'display.expand_frame_repr', 'info', 'display.show_dimensions', 'truncate'): + self.assertTrue('5 rows' in str(df)) + self.assertTrue('5 rows' in df._repr_html_()) + with option_context('display.max_rows', 10, 'display.max_columns', 40, 'display.width', + 500, 'display.expand_frame_repr', 'info', 'display.show_dimensions', 'truncate'): + self.assertFalse('5 rows' in str(df)) + self.assertFalse('5 rows' in df._repr_html_()) + def test_to_html(self): # big mixed biggie = DataFrame({'A': randn(200),