Skip to content

Commit 0912936

Browse files
author
Tom Augspurger
committed
Merge pull request #7130 from TomAugspurger/max_info_columns
BUG/API: info repr should honor display.max_info_columns
2 parents b453fa3 + 684ce0b commit 0912936

File tree

5 files changed

+89
-9
lines changed

5 files changed

+89
-9
lines changed

doc/source/release.rst

+1
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ Bug Fixes
515515
- Bug in the HTML repr of a truncated Series or DataFrame not showing the class name with the `large_repr` set to 'info'
516516
(:issue:`7105`)
517517
- Bug in ``DatetimeIndex`` specifying ``freq`` raises ``ValueError`` when passed value is too short (:issue:`7098`)
518+
- Fixed a bug with the `info` repr not honoring the `display.max_info_columns` setting (:issue:`6939`)
518519

519520
pandas 0.13.1
520521
-------------

doc/source/v0.14.0.txt

+6
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ API changes
210210
# this now raises for arith ops like ``+``, ``*``, etc.
211211
NotImplementedError: operator '*' not implemented for bool dtypes
212212

213+
213214
.. _whatsnew_0140.display:
214215

215216
Display Changes
@@ -239,6 +240,11 @@ Display Changes
239240
length of the series (:issue:`7101`)
240241
- Fixed a bug in the HTML repr of a truncated Series or DataFrame not showing the class name with the
241242
`large_repr` set to 'info' (:issue:`7105`)
243+
- The `verbose` keyword in ``DataFrame.info()``, which controls whether to shorten the ``info``
244+
representation, is now ``None`` by default. This will follow the global setting in
245+
``display.max_info_columns``. The global setting can be overriden with ``verbose=True`` or
246+
``verbose=False``.
247+
- Fixed a bug with the `info` repr not honoring the `display.max_info_columns` setting (:issue:`6939`)
242248

243249
.. _whatsnew_0140.groupby:
244250

pandas/core/frame.py

+25-9
Original file line numberDiff line numberDiff line change
@@ -1392,17 +1392,20 @@ def to_latex(self, buf=None, columns=None, col_space=None, colSpace=None,
13921392
if buf is None:
13931393
return formatter.buf.getvalue()
13941394

1395-
def info(self, verbose=True, buf=None, max_cols=None):
1395+
def info(self, verbose=None, buf=None, max_cols=None):
13961396
"""
13971397
Concise summary of a DataFrame.
13981398
13991399
Parameters
14001400
----------
1401-
verbose : boolean, default True
1402-
If False, don't print column count summary
1401+
verbose : {None, True, False}, optional
1402+
Whether to print the full summary.
1403+
None follows the `display.max_info_columns` setting.
1404+
True or False overrides the `display.max_info_columns` setting.
14031405
buf : writable buffer, defaults to sys.stdout
14041406
max_cols : int, default None
1405-
Determines whether full summary or short summary is printed
1407+
Determines whether full summary or short summary is printed.
1408+
None follows the `display.max_info_columns` setting.
14061409
"""
14071410
from pandas.core.format import _put_lines
14081411

@@ -1429,8 +1432,10 @@ def info(self, verbose=True, buf=None, max_cols=None):
14291432
max_rows = get_option('display.max_info_rows', len(self) + 1)
14301433

14311434
show_counts = ((len(self.columns) <= max_cols) and
1432-
(len(self) < max_rows))
1433-
if verbose:
1435+
(len(self) < max_rows))
1436+
exceeds_info_cols = len(self.columns) > max_cols
1437+
1438+
def _verbose_repr():
14341439
lines.append('Data columns (total %d columns):' %
14351440
len(self.columns))
14361441
space = max([len(com.pprint_thing(k)) for k in self.columns]) + 4
@@ -1442,22 +1447,33 @@ def info(self, verbose=True, buf=None, max_cols=None):
14421447
if len(cols) != len(counts): # pragma: no cover
14431448
raise AssertionError('Columns must equal counts (%d != %d)' %
14441449
(len(cols), len(counts)))
1445-
tmpl = "%s non-null %s"
1450+
tmpl = "%s non-null %s"
14461451

14471452
dtypes = self.dtypes
14481453
for i, col in enumerate(self.columns):
14491454
dtype = dtypes[col]
14501455
col = com.pprint_thing(col)
14511456

1452-
count= ""
1457+
count = ""
14531458
if show_counts:
14541459
count = counts.iloc[i]
14551460

14561461
lines.append(_put_str(col, space) +
14571462
tmpl % (count, dtype))
1458-
else:
1463+
1464+
def _non_verbose_repr():
14591465
lines.append(self.columns.summary(name='Columns'))
14601466

1467+
if verbose:
1468+
_verbose_repr()
1469+
elif verbose is False: # specifically set to False, not nesc None
1470+
_non_verbose_repr()
1471+
else:
1472+
if exceeds_info_cols:
1473+
_non_verbose_repr()
1474+
else:
1475+
_verbose_repr()
1476+
14611477
counts = self.get_dtype_counts()
14621478
dtypes = ['%s(%d)' % k for k in sorted(compat.iteritems(counts))]
14631479
lines.append('dtypes: %s' % ', '.join(dtypes))

pandas/tests/test_format.py

+22
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ def has_info_repr(df):
3838
c2 = r.split('\n')[0].startswith(r"&lt;class") # _repr_html_
3939
return c1 or c2
4040

41+
def has_non_verbose_info_repr(df):
42+
has_info = has_info_repr(df)
43+
r = repr(df)
44+
nv = len(r.split('\n')) == 4 # 1. <class>, 2. Index, 3. Columns, 4. dtype
45+
return has_info and nv
46+
4147
def has_horizontally_truncated_repr(df):
4248
r = repr(df)
4349
return any(l.strip().endswith('...') for l in r.splitlines())
@@ -1573,6 +1579,22 @@ def test_info_repr(self):
15731579
with option_context('display.large_repr', 'info'):
15741580
assert has_info_repr(df)
15751581

1582+
def test_info_repr_max_cols(self):
1583+
# GH #6939
1584+
df = DataFrame(randn(10, 5))
1585+
with option_context('display.large_repr', 'info',
1586+
'display.max_columns', 1,
1587+
'display.max_info_columns', 4):
1588+
self.assertTrue(has_non_verbose_info_repr(df))
1589+
1590+
with option_context('display.large_repr', 'info',
1591+
'display.max_columns', 1,
1592+
'display.max_info_columns', 5):
1593+
self.assertFalse(has_non_verbose_info_repr(df))
1594+
1595+
# test verbose overrides
1596+
# fmt.set_option('display.max_info_columns', 4) # exceeded
1597+
15761598
def test_info_repr_html(self):
15771599
max_rows = get_option('display.max_rows')
15781600
max_cols = get_option('display.max_columns')

pandas/tests/test_frame.py

+35
Original file line numberDiff line numberDiff line change
@@ -6326,6 +6326,41 @@ def test_info_shows_column_dtypes(self):
63266326
name = '%d %d non-null %s' % (i, n, dtype)
63276327
assert name in res
63286328

6329+
def test_info_max_cols(self):
6330+
df = DataFrame(np.random.randn(10, 5))
6331+
for len_, verbose in [(4, None), (4, False), (9, True)]:
6332+
# For verbose always ^ setting ^ summarize ^ full output
6333+
with pd.option_context('max_info_columns', 4):
6334+
buf = StringIO()
6335+
df.info(buf=buf, verbose=verbose)
6336+
res = buf.getvalue()
6337+
self.assertEqual(len(res.split('\n')), len_)
6338+
6339+
for len_, verbose in [(9, None), (4, False), (9, True)]:
6340+
6341+
# max_cols no exceeded
6342+
with pd.option_context('max_info_columns', 5):
6343+
buf = StringIO()
6344+
df.info(buf=buf, verbose=verbose)
6345+
res = buf.getvalue()
6346+
self.assertEqual(len(res.split('\n')), len_)
6347+
6348+
for len_, max_cols in [(9, 5), (4, 4)]:
6349+
# setting truncates
6350+
with pd.option_context('max_info_columns', 4):
6351+
buf = StringIO()
6352+
df.info(buf=buf, max_cols=max_cols)
6353+
res = buf.getvalue()
6354+
self.assertEqual(len(res.split('\n')), len_)
6355+
6356+
# setting wouldn't truncate
6357+
with pd.option_context('max_info_columns', 5):
6358+
buf = StringIO()
6359+
df.info(buf=buf, max_cols=max_cols)
6360+
res = buf.getvalue()
6361+
self.assertEqual(len(res.split('\n')), len_)
6362+
6363+
63296364
def test_dtypes(self):
63306365
self.mixed_frame['bool'] = self.mixed_frame['A'] > 0
63316366
result = self.mixed_frame.dtypes

0 commit comments

Comments
 (0)