Skip to content

Commit 5602b98

Browse files
committed
ENH: refactor formatting stuff. also close #755
1 parent 57159d7 commit 5602b98

File tree

11 files changed

+767
-724
lines changed

11 files changed

+767
-724
lines changed

pandas/__init__.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
from pandas.sparse.api import *
2424
from pandas.stats.api import *
2525

26-
from pandas.core.common import set_printoptions, reset_printoptions
27-
from pandas.core.common import set_eng_float_format
26+
from pandas.core.format import (set_printoptions, reset_printoptions,
27+
set_eng_float_format)
2828
from pandas.io.parsers import read_csv, read_table, read_clipboard, ExcelFile
2929
from pandas.io.pytables import HDFStore
3030
from pandas.util.testing import debug

pandas/core/api.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
from pandas.core.datetools import DateOffset
66
import pandas.core.datetools as datetools
77

8-
from pandas.core.common import isnull, notnull, set_printoptions, save, load
8+
from pandas.core.common import isnull, notnull, save, load
9+
from pandas.core.format import set_printoptions
910
from pandas.core.index import Index, Int64Index, Factor, MultiIndex
1011
from pandas.core.daterange import DateRange
1112
from pandas.core.series import Series, TimeSeries

pandas/core/common.py

+4-257
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@
1616
from numpy.lib.format import read_array, write_array
1717
import numpy as np
1818

19-
import decimal
20-
import math
21-
2219
import pandas._tseries as lib
2320
from pandas.util import py3compat
2421
import codecs
@@ -370,260 +367,6 @@ def _try_sort(iterable):
370367
except Exception:
371368
return listed
372369

373-
#-------------------------------------------------------------------------------
374-
# Global formatting options
375-
376-
def set_printoptions(precision=None, column_space=None, max_rows=None,
377-
max_columns=None, colheader_justify='right'):
378-
"""
379-
Alter default behavior of DataFrame.toString
380-
381-
precision : int
382-
Floating point output precision (number of significant digits)
383-
column_space : int
384-
Default space for DataFrame columns, defaults to 12
385-
max_rows : int
386-
max_columns : int
387-
max_rows and max_columns are used in __repr__() methods to decide if
388-
to_string() or info() is used to render an object to a string.
389-
Either one, or both can be set to 0 (experimental). Pandas will figure
390-
out how big the terminal is and will not display more rows or/and
391-
columns that can fit on it.
392-
"""
393-
if precision is not None:
394-
print_config.precision = precision
395-
if column_space is not None:
396-
print_config.column_space = column_space
397-
if max_rows is not None:
398-
print_config.max_rows = max_rows
399-
if max_columns is not None:
400-
print_config.max_columns = max_columns
401-
if colheader_justify is not None:
402-
print_config.colheader_justify = colheader_justify
403-
404-
def reset_printoptions():
405-
print_config.reset()
406-
407-
class EngFormatter(object):
408-
"""
409-
Formats float values according to engineering format.
410-
411-
Based on matplotlib.ticker.EngFormatter
412-
"""
413-
414-
# The SI engineering prefixes
415-
ENG_PREFIXES = {
416-
-24: "y",
417-
-21: "z",
418-
-18: "a",
419-
-15: "f",
420-
-12: "p",
421-
-9: "n",
422-
-6: "u",
423-
-3: "m",
424-
0: "",
425-
3: "k",
426-
6: "M",
427-
9: "G",
428-
12: "T",
429-
15: "P",
430-
18: "E",
431-
21: "Z",
432-
24: "Y"
433-
}
434-
435-
def __init__(self, accuracy=None, use_eng_prefix=False):
436-
self.accuracy = accuracy
437-
self.use_eng_prefix = use_eng_prefix
438-
439-
def __call__(self, num):
440-
""" Formats a number in engineering notation, appending a letter
441-
representing the power of 1000 of the original number. Some examples:
442-
443-
>>> format_eng(0) # for self.accuracy = 0
444-
' 0'
445-
446-
>>> format_eng(1000000) # for self.accuracy = 1,
447-
# self.use_eng_prefix = True
448-
' 1.0M'
449-
450-
>>> format_eng("-1e-6") # for self.accuracy = 2
451-
# self.use_eng_prefix = False
452-
'-1.00E-06'
453-
454-
@param num: the value to represent
455-
@type num: either a numeric value or a string that can be converted to
456-
a numeric value (as per decimal.Decimal constructor)
457-
458-
@return: engineering formatted string
459-
"""
460-
461-
dnum = decimal.Decimal(str(num))
462-
463-
sign = 1
464-
465-
if dnum < 0: # pragma: no cover
466-
sign = -1
467-
dnum = -dnum
468-
469-
if dnum != 0:
470-
pow10 = decimal.Decimal(int(math.floor(dnum.log10()/3)*3))
471-
else:
472-
pow10 = decimal.Decimal(0)
473-
474-
pow10 = pow10.min(max(self.ENG_PREFIXES.keys()))
475-
pow10 = pow10.max(min(self.ENG_PREFIXES.keys()))
476-
int_pow10 = int(pow10)
477-
478-
if self.use_eng_prefix:
479-
prefix = self.ENG_PREFIXES[int_pow10]
480-
else:
481-
if int_pow10 < 0:
482-
prefix = 'E-%02d' % (-int_pow10)
483-
else:
484-
prefix = 'E+%02d' % int_pow10
485-
486-
mant = sign*dnum/(10**pow10)
487-
488-
if self.accuracy is None: # pragma: no cover
489-
format_str = u"% g%s"
490-
else:
491-
format_str = (u"%% .%if%%s" % self.accuracy )
492-
493-
formatted = format_str % (mant, prefix)
494-
495-
return formatted #.strip()
496-
497-
def set_eng_float_format(precision=None, accuracy=3, use_eng_prefix=False):
498-
"""
499-
Alter default behavior on how float is formatted in DataFrame.
500-
Format float in engineering format. By accuracy, we mean the number of
501-
decimal digits after the floating point.
502-
503-
See also EngFormatter.
504-
"""
505-
if precision is not None: # pragma: no cover
506-
import warnings
507-
warnings.warn("'precision' parameter in set_eng_float_format is "
508-
"being renamed to 'accuracy'" , FutureWarning)
509-
accuracy = precision
510-
511-
print_config.float_format = EngFormatter(accuracy, use_eng_prefix)
512-
print_config.column_space = max(12, accuracy + 9)
513-
514-
def _stringify(col):
515-
# unicode workaround
516-
return unicode(col)
517-
#if isinstance(col, tuple):
518-
# return str(col)
519-
#else:
520-
# return '%s' % console_encode(col)
521-
522-
def _float_format_default(v, width=None):
523-
"""
524-
Take a float and its formatted representation and if it needs extra space
525-
to fit the width, reformat it to that width.
526-
"""
527-
528-
fmt_str = '%% .%dg' % print_config.precision
529-
formatted = fmt_str % v
530-
531-
if width is None:
532-
return formatted
533-
534-
extra_spc = width - len(formatted)
535-
536-
if extra_spc <= 0:
537-
return formatted
538-
539-
if 'e' in formatted:
540-
# we have something like 1e13 or 1.23e13
541-
base, exp = formatted.split('e')
542-
543-
if '.' in base:
544-
# expand fraction by extra space
545-
whole, frac = base.split('.')
546-
fmt_str = '%%.%df' % (len(frac) + extra_spc)
547-
frac = fmt_str % float("0.%s" % frac)
548-
base = whole + frac[1:]
549-
else:
550-
if extra_spc > 1:
551-
# enough room for fraction
552-
fmt_str = '%% .%df' % (extra_spc - 1)
553-
base = fmt_str % float(base)
554-
else:
555-
# enough room for decimal point only
556-
base += '.'
557-
558-
return base + 'e' + exp
559-
else:
560-
# we have something like 123 or 123.456
561-
if '.' in formatted:
562-
# expand fraction by extra space
563-
wholel, fracl = map(len, formatted.split("."))
564-
fmt_str = '%% .%df' % (fracl + extra_spc)
565-
else:
566-
if extra_spc > 1:
567-
# enough room for fraction
568-
fmt_str = '%% .%df' % (extra_spc - 1)
569-
else:
570-
# enough room for decimal point only
571-
fmt_str = '% d.'
572-
573-
return fmt_str % v
574-
575-
def _format(s, dtype, space=None, na_rep=None, float_format=None,
576-
col_width=None):
577-
def _just_help(x):
578-
if space is None:
579-
return x
580-
return x[:space].ljust(space)
581-
582-
def _make_float_format(x):
583-
if na_rep is not None and isnull(x):
584-
if np.isnan(x):
585-
x = ' ' + na_rep
586-
return _just_help('%s' % x)
587-
588-
if float_format:
589-
formatted = float_format(x)
590-
elif print_config.float_format:
591-
formatted = print_config.float_format(x)
592-
else:
593-
formatted = _float_format_default(x, col_width)
594-
595-
return _just_help(formatted)
596-
597-
def _make_int_format(x):
598-
return _just_help('% d' % x)
599-
600-
if is_float_dtype(dtype):
601-
return _make_float_format(s)
602-
elif is_integer_dtype(dtype):
603-
return _make_int_format(s)
604-
else:
605-
if na_rep is not None and lib.checknull(s):
606-
if s is None:
607-
return 'None'
608-
return na_rep
609-
else:
610-
# object dtype
611-
return _just_help('%s' % _stringify(s))
612-
613-
class _GlobalPrintConfig(object):
614-
def __init__(self):
615-
self.precision = 4
616-
self.float_format = None
617-
self.column_space = 12
618-
self.max_rows = 200
619-
self.max_columns = 0
620-
self.colheader_justify = 'right'
621-
622-
def reset(self):
623-
self.__init__()
624-
625-
print_config = _GlobalPrintConfig()
626-
627370
#------------------------------------------------------------------------------
628371
# miscellaneous python tools
629372

@@ -755,6 +498,10 @@ def _asarray_tuplesafe(values, dtype=None):
755498

756499
return result
757500

501+
def _stringify(col):
502+
# unicode workaround
503+
return unicode(col)
504+
758505
def _maybe_make_list(obj):
759506
if obj is not None and not isinstance(obj, (tuple, list)):
760507
return [obj]

0 commit comments

Comments
 (0)