44# pylint: disable=W0141
55
66import sys
7- import re
87
98from pandas .core .base import PandasObject
10- from pandas .core .common import adjoin , isnull , notnull
9+ from pandas .core .common import adjoin , notnull
1110from pandas .core .index import Index , MultiIndex , _ensure_index
1211from pandas import compat
1312from pandas .compat import (StringIO , lzip , range , map , zip , reduce , u ,
1413 OrderedDict )
1514from pandas .util .terminal import get_terminal_size
16- from pandas .core .config import get_option , set_option , reset_option
15+ from pandas .core .config import get_option , set_option
1716import pandas .core .common as com
1817import pandas .lib as lib
1918from pandas .tslib import iNaT , Timestamp , Timedelta
2221
2322import itertools
2423import csv
25- from datetime import time
2624
2725from pandas .tseries .period import PeriodIndex , DatetimeIndex
2826
@@ -321,30 +319,69 @@ def __init__(self, frame, buf=None, columns=None, col_space=None,
321319 self ._chk_truncate ()
322320
323321 def _chk_truncate (self ):
322+ '''
323+ Checks whether the frame should be truncated. If so, slices
324+ the frame up.
325+ '''
324326 from pandas .tools .merge import concat
325327
326- truncate_h = self . max_cols and ( len ( self . columns ) > self . max_cols )
327- truncate_v = self .max_rows and ( len ( self . frame ) > self . max_rows )
328+ # Column of which first element is used to determine width of a dot col
329+ self .tr_size_col = - 1
328330
329331 # Cut the data to the information actually printed
330332 max_cols = self .max_cols
331333 max_rows = self .max_rows
334+
335+ if max_cols == 0 or max_rows == 0 : # assume we are in the terminal (why else = 0)
336+ (w ,h ) = get_terminal_size ()
337+ self .w = w
338+ self .h = h
339+ if self .max_rows == 0 :
340+ dot_row = 1
341+ prompt_row = 1
342+ if self .show_dimensions :
343+ show_dimension_rows = 3
344+ n_add_rows = self .header + dot_row + show_dimension_rows + prompt_row
345+ max_rows_adj = self .h - n_add_rows # rows available to fill with actual data
346+ self .max_rows_adj = max_rows_adj
347+
348+ # Format only rows and columns that could potentially fit the screen
349+ if max_cols == 0 and len (self .frame .columns ) > w :
350+ max_cols = w
351+ if max_rows == 0 and len (self .frame ) > h :
352+ max_rows = h
353+
354+ if not hasattr (self ,'max_rows_adj' ):
355+ self .max_rows_adj = max_rows
356+ if not hasattr (self ,'max_cols_adj' ):
357+ self .max_cols_adj = max_cols
358+
359+ max_cols_adj = self .max_cols_adj
360+ max_rows_adj = self .max_rows_adj
361+
362+ truncate_h = max_cols_adj and (len (self .columns ) > max_cols_adj )
363+ truncate_v = max_rows_adj and (len (self .frame ) > max_rows_adj )
364+
332365 frame = self .frame
333366 if truncate_h :
334- if max_cols > 1 :
335- col_num = (max_cols // 2 )
336- frame = concat ( (frame .iloc [:,:col_num ],frame .iloc [:,- col_num :]),axis = 1 )
337- else :
338- col_num = max_cols
367+ if max_cols_adj == 0 :
368+ col_num = len (frame .columns )
369+ elif max_cols_adj == 1 :
339370 frame = frame .iloc [:,:max_cols ]
371+ col_num = max_cols
372+ else :
373+ col_num = (max_cols_adj // 2 )
374+ frame = concat ( (frame .iloc [:,:col_num ],frame .iloc [:,- col_num :]),axis = 1 )
340375 self .tr_col_num = col_num
341376 if truncate_v :
342- if max_rows > 1 :
343- row_num = max_rows // 2
344- frame = concat ( (frame .iloc [:row_num ,:],frame .iloc [- row_num :,:]) )
345- else :
377+ if max_rows_adj == 0 :
378+ row_num = len (frame )
379+ if max_rows_adj == 1 :
346380 row_num = max_rows
347381 frame = frame .iloc [:max_rows ,:]
382+ else :
383+ row_num = max_rows_adj // 2
384+ frame = concat ( (frame .iloc [:row_num ,:],frame .iloc [- row_num :,:]) )
348385 self .tr_row_num = row_num
349386
350387 self .tr_frame = frame
@@ -360,13 +397,12 @@ def _to_str_columns(self):
360397 frame = self .tr_frame
361398
362399 # may include levels names also
363- str_index = self ._get_formatted_index (frame )
364400
401+ str_index = self ._get_formatted_index (frame )
365402 str_columns = self ._get_formatted_column_labels (frame )
366403
367404 if self .header :
368405 stringified = []
369- col_headers = frame .columns
370406 for i , c in enumerate (frame ):
371407 cheader = str_columns [i ]
372408 max_colwidth = max (self .col_space or 0 ,
@@ -389,7 +425,6 @@ def _to_str_columns(self):
389425 else :
390426 stringified = []
391427 for i , c in enumerate (frame ):
392- formatter = self ._get_formatter (i )
393428 fmt_values = self ._format_col (i )
394429 fmt_values = _make_fixed_width (fmt_values , self .justify ,
395430 minimum = (self .col_space or 0 ))
@@ -406,8 +441,8 @@ def _to_str_columns(self):
406441
407442 if truncate_h :
408443 col_num = self .tr_col_num
409- col_width = len (strcols [col_num ][0 ]) # infer from column header
410- strcols .insert (col_num + 1 , ['...' .center (col_width )] * (len (str_index )))
444+ col_width = len (strcols [self . tr_size_col ][0 ]) # infer from column header
445+ strcols .insert (self . tr_col_num + 1 , ['...' .center (col_width )] * (len (str_index )))
411446 if truncate_v :
412447 n_header_rows = len (str_index ) - len (frame )
413448 row_num = self .tr_row_num
@@ -424,19 +459,19 @@ def _to_str_columns(self):
424459 if ix == 0 :
425460 dot_str = my_str .ljust (cwidth )
426461 elif is_dot_col :
462+ cwidth = len (strcols [self .tr_size_col ][0 ])
427463 dot_str = my_str .center (cwidth )
428464 else :
429465 dot_str = my_str .rjust (cwidth )
430466
431467 strcols [ix ].insert (row_num + n_header_rows , dot_str )
432-
433468 return strcols
434469
435470 def to_string (self ):
436471 """
437472 Render a DataFrame to a console-friendly tabular output.
438473 """
439-
474+ from pandas import Series
440475 frame = self .frame
441476
442477 if len (frame .columns ) == 0 or len (frame .index ) == 0 :
@@ -447,10 +482,40 @@ def to_string(self):
447482 text = info_line
448483 else :
449484 strcols = self ._to_str_columns ()
450- if self .line_width is None :
485+ if self .line_width is None : # no need to wrap around just print the whole frame
451486 text = adjoin (1 , * strcols )
452- else :
487+ elif not isinstance ( self . max_cols , int ) or self . max_cols > 0 : # perhaps need to wrap around
453488 text = self ._join_multiline (* strcols )
489+ else : # max_cols == 0. Try to fit frame to terminal
490+ text = adjoin (1 , * strcols ).split ('\n ' )
491+ row_lens = Series (text ).apply (len )
492+ max_len_col_ix = np .argmax (row_lens )
493+ max_len = row_lens [max_len_col_ix ]
494+ headers = [ele [0 ] for ele in strcols ]
495+ # Size of last col determines dot col size. See `self._to_str_columns
496+ size_tr_col = len (headers [self .tr_size_col ])
497+ max_len += size_tr_col # Need to make space for largest row plus truncate (dot) col
498+ dif = max_len - self .w
499+ adj_dif = dif
500+ col_lens = Series ([Series (ele ).apply (len ).max () for ele in strcols ])
501+ n_cols = len (col_lens )
502+ counter = 0
503+ while adj_dif > 0 and n_cols > 1 :
504+ counter += 1
505+ mid = int (round (n_cols / 2. ))
506+ mid_ix = col_lens .index [mid ]
507+ col_len = col_lens [mid_ix ]
508+ adj_dif -= ( col_len + 1 ) # adjoin adds one
509+ col_lens = col_lens .drop (mid_ix )
510+ n_cols = len (col_lens )
511+ max_cols_adj = n_cols - self .index # subtract index column
512+ self .max_cols_adj = max_cols_adj
513+
514+ # Call again _chk_truncate to cut frame appropriately
515+ # and then generate string representation
516+ self ._chk_truncate ()
517+ strcols = self ._to_str_columns ()
518+ text = adjoin (1 , * strcols )
454519
455520 self .buf .writelines (text )
456521
@@ -472,8 +537,8 @@ def _join_multiline(self, *strcols):
472537 col_bins = _binify (col_widths , lwidth )
473538 nbins = len (col_bins )
474539
475- if self .max_rows and len ( self . frame ) > self . max_rows :
476- nrows = self .max_rows + 1
540+ if self .truncate_v :
541+ nrows = self .max_rows_adj + 1
477542 else :
478543 nrows = len (self .frame )
479544
@@ -654,6 +719,7 @@ def space_format(x,y):
654719 for x in str_columns :
655720 x .append ('' )
656721
722+ # self.str_columns = str_columns
657723 return str_columns
658724
659725 @property
0 commit comments