Files
tableprint/tableprint.py
2016-05-02 14:42:13 -07:00

277 lines
7.3 KiB
Python

"""
Tableprint
A module to print and display ASCII formatted tables of data
Usage
-----
>>> data = np.random.randn(10,3)
>>> headers = ['Column A', 'Column B', 'Column C']
>>> tableprint.table(data, headers)
"""
from __future__ import print_function, unicode_literals
from six import string_types
import numpy as np
__all__ = ['table', 'row', 'header', 'hr', 'humantime', 'frame']
__version__ = '0.2.1'
def table(data, headers, format_spec='5g', column_width=10,
outer_char='\u2502', corner_char='\u253C', line_char='\u2500'):
"""
Print an ASCII table with the given data
Parameters
----------
data : array_like
An (m x n) array containing the data to print (m rows of n columns)
headers : list
A list of n strings consisting of the header of each of the n columns
column_width : int, optional
The width of each column in the table (Default: 10)
outer_char : string, optional
The character defining the outer border of the table (Default: '|')
corner_char : string, optional
Printed at the junctions of the table lines (Default: '+')
line_char : string, optional
Character as part of each horizontal rule (Default: '-')
format_spec : string, optional
Format specification for formatting numbers (Default: '5g')
"""
# get the header string
headerstr = header(headers, column_width=column_width, outer_char=outer_char)
# parse each row
tablestr = [headerstr] + [row(d, column_width=column_width, format_spec=format_spec,
outer_char=outer_char) for d in data]
# only add the final border if there was data in the table
if len(data) > 0:
tablestr += [hr(len(headers), column_width=column_width,
corner_char=corner_char, line_char=line_char)]
# print the table
print('\n'.join(tablestr))
def header(headers, column_width=10, outer_char='\u2502', add_hr=True):
"""
Returns a formatted ASCII row of column header strings
Parameters
----------
headers : list of strings
A list of n strings, the column headers
column_width : int
The width of each column (Default: 10)
outer_char : string
A character printed at the edges of each column (Default: '|')
Returns
-------
headerstr : string
A string consisting of the full header row to print
"""
# string formatter
fmt = map(lambda x: '{:<' + str(column_width) + '}', headers)
# build the base string
basestr = (' %s ' % outer_char).join(fmt)
# build the formatted str
headerstr = outer_char + basestr.format(*headers) + outer_char
if add_hr:
hr_string = hr(len(headers), column_width=column_width)
headerstr = '\n'.join([hr_string, headerstr, hr_string])
return headerstr
def row(values, column_width=10, format_spec='5g', outer_char='\u2502'):
"""
Returns a formatted ASCII row of data
Parameters
----------
values : array_like
An iterable array of data (numbers of strings), each value is printed in a separate column
column_width : int
The width of each column (Default: 10)
format_spec : string
The precision format string used to format numbers in the values array (Default: '5g')
outer_char : string
A character printed at the edges of each column (Default : '|')
Returns
-------
rowstr : string
A string consisting of the full row of data to print
"""
assert isinstance(format_spec, string_types) | (type(format_spec) is list), \
"format_spec must be a string or list of strings"
if isinstance(format_spec, string_types):
format_spec = [format_spec] * len(list(values))
# mapping function for string formatting
def mapdata(val):
# unpack
d, prec = val
if isinstance(d, string_types):
return ('{:>%i}' % column_width).format(d)
elif isinstance(d, (int, float, np.integer, np.float)):
return ('{:>%i.%s}' % (column_width, prec)).format(d)
else:
raise ValueError('Elements in the values array must be strings, ints, or floats')
# string formatter
fmt = map(mapdata, zip(values, format_spec))
# build the base string
basestr = (' %s ' % outer_char).join(fmt)
# build the formatted string
rowstr = outer_char + basestr + outer_char
return rowstr
def hr(ncols, column_width=10, corner_char='\u253C', line_char='\u2500'):
"""
Returns a formatted string used as a border between table rows
Parameters
----------
ncols : int
The number of columns in the table
column_width : int
The width of each column (Default: 10)
corner_char : string
A character printed at the intersection of column edges and the row border (Default: '+')
line_char : string
A character printed in between column edges, defines the row border (Default: '-')
Returns
-------
rowstr : string
A string consisting of the row border to print
"""
hrstr = corner_char.join([('{:%s^%i}' % (line_char, column_width + 2)).format('') for _ in range(ncols)])
return corner_char + hrstr[1:-1] + corner_char
def humantime(t):
"""
Converts a time in seconds to a reasonable human readable time
Parameters
----------
t : float
The number of seconds
Returns
-------
time : string
The human readable formatted value of the given time
"""
try:
t = float(t)
except (ValueError, TypeError):
raise ValueError("Input must be numeric")
# weeks
if t >= 7*60*60*24:
weeks = np.floor(t / (7.*60.*60.*24.))
timestr = "{:g} weeks, ".format(weeks) + humantime(t % (7*60*60*24))
# days
elif t >= 60*60*24:
days = np.floor(t / (60.*60.*24.))
timestr = "{:g} days, ".format(days) + humantime(t % (60*60*24))
# hours
elif t >= 60*60:
hours = np.floor(t / (60.*60.))
timestr = "{:g} hours, ".format(hours) + humantime(t % (60*60))
# minutes
elif t >= 60:
minutes = np.floor(t / 60.)
timestr = "{:g} min., ".format(minutes) + humantime(t % 60)
# seconds
elif (t >= 1) | (t == 0):
timestr = "{:g} s".format(t)
# milliseconds
elif t >= 1e-3:
timestr = "{:g} ms".format(t*1e3)
# microseconds
elif t >= 1e-6:
timestr = u"{:g} \u03BCs".format(t*1e6)
# nanoseconds or smaller
else:
timestr = "{:g} ns".format(t*1e9)
return timestr
def frame(dataframe, **kwargs):
"""
Print an ASCII table using the given pandas DataFrame
Parameters
----------
dataframe : DataFrame
A pandas DataFrame with consisting of the table to print
column_width : int, optional
The width of each column in the table (Default: 10)
outer_char : string, optional
The character defining the outer border of the table (Default: '|')
corner_char : string, optional
Printed at the junctions of the table lines (Default: '+')
line_char : string, optional
Character as part of each horizontal rule (Default: '-')
format_spec : string, optional
Format specification for formatting numbers (Default: '5g')
"""
table(np.array(dataframe), list(dataframe.columns), **kwargs)