[Scipy-svn] r2654 - trunk/Lib/sandbox/timeseries
scipy-svn at scipy.org
scipy-svn at scipy.org
Tue Jan 30 18:04:00 EST 2007
Author: mattknox_ca
Date: 2007-01-30 17:03:57 -0600 (Tue, 30 Jan 2007)
New Revision: 2654
Modified:
trunk/Lib/sandbox/timeseries/reportlib.py
Log:
added footer capability, and bunch of other changes
Modified: trunk/Lib/sandbox/timeseries/reportlib.py
===================================================================
--- trunk/Lib/sandbox/timeseries/reportlib.py 2007-01-30 21:11:09 UTC (rev 2653)
+++ trunk/Lib/sandbox/timeseries/reportlib.py 2007-01-30 23:03:57 UTC (rev 2654)
@@ -38,7 +38,6 @@
return self.f(item)
-
def report(*tseries, **kwargs):
"""generate a table report of *tseries with dates in the left column.
@@ -51,7 +50,20 @@
- `header_row` (list, *[None]*) : optional list of column headers. Length
must be equal to len(tseries) (no date column header specified) or
len(tseries)+1 (first header is assumed to be date column header)
- - `header_char` : Character to be used for the row separator line
+ - `header_char` (string, *['-']*): Character to be used for the row separator
+ line between the header and first row of data. None for no separator. This
+ is ignored if `header_row` is None.
+ - `row_char` (string, *[None]*): Character to be used for the row separator
+ line between each row of data. None for no separator
+ - `footer_func` (List of functions or single function, *[None]*) : A function or
+ list of functions for summarizing each data column in the report. For example,
+ ma.sum to get the sum of the column. If a list of functions is provided
+ there must be exactly one function for each column.
+ - `footer_char` (string, *['-']*): Character to be used for the row separator
+ line between the last row of data and the footer. None for no separator. This
+ is ignored if `footer_func` is None.
+ - `footer_label` (string, *[None]*) : label for the footer row. This is
+ ignored if footer_func is None.
- `justify` (List of strings or single string, *[None]*) : Determines how are
data justified in their column. If not specified, the date column and string
columns are left justified, and everything else is right justified. If a
@@ -105,6 +117,10 @@
dates = kwargs.pop('dates', None)
header_row = kwargs.pop('header_row', None)
header_char = kwargs.pop('header_char', '-')
+ row_char = kwargs.pop('row_char', None)
+ footer_label = kwargs.pop('footer_label', None)
+ footer_char = kwargs.pop('footer_char', '-')
+ footer_func = kwargs.pop('footer_func', None)
delim = kwargs.pop('delim', ' | ')
justify = kwargs.pop('justify', None)
prefix = kwargs.pop('prefix', '')
@@ -113,6 +129,7 @@
datefmt = kwargs.pop('datefmt', None)
fmtfunc = kwargs.pop('fmtfunc', str)
+
if type(fmtfunc) != types.ListType:
fmtfunc = [fmtfunc_wrapper(fmtfunc, mask_rep)]*len(tseries)
else:
@@ -124,7 +141,7 @@
raise KeyError("Unrecognized keyword(s): %s" % (", ".join(kwargs.keys())))
if header_row is not None:
- hasHeader=True
+ has_header=True
if len(header_row) == len(tseries)+1:
# label for date column included
rows = [header_row]
@@ -132,7 +149,7 @@
# label for date column not included
rows = [['']+header_row]
else:
- hasHeader=False
+ has_header=False
rows=[]
if justify is not None:
@@ -157,17 +174,32 @@
else:
def datefmt_func(date): return date.strfmt(datefmt)
- tseries = ts.align_series(*tseries)
-
if dates is None:
+ tseries = ts.align_series(*tseries)
dates = td.date_array(start_date=tseries[0].start_date,
end_date=tseries[0].end_date)
+ else:
+ tseries = ts.align_series(start_date=dates[0], end_date=dates[-1], *tseries)
for d in dates:
rows.append([datefmt_func(d)]+[fmtfunc[i](ser[d]) for i, ser in enumerate(tseries)])
+
+ if footer_func is not None:
+ has_footer=True
+ if type(footer_func) != types.ListType:
+ footer_func = [footer_func]*len(tseries)
- return indent(rows, hasHeader=hasHeader, headerChar=header_char,
- delim=delim, justify=justify, separateRows=False,
+ if footer_label is None: footer_label = ['']
+ else: footer_label = [footer_label]
+ rows.append(footer_label + [fmtfunc[i](footer_func[i](ser)) for i, ser in enumerate(tseries)])
+ else:
+ has_footer=False
+
+ return indent(rows,
+ has_header=has_header, header_char=header_char,
+ has_footer=has_footer, footer_char=footer_char,
+ separate_rows=separate_rows, row_char=row_char,
+ delim=delim, justify=justify,
prefix=prefix, postfix=postfix, wrapfunc=wrapfunc)
@@ -175,18 +207,22 @@
# written by George Sakkis
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/267662
-def indent(rows, hasHeader=False, headerChar='-', delim=' | ', justify=None,
- separateRows=False, prefix='', postfix='', wrapfunc=lambda x:x):
+def indent(rows,
+ has_header=False, header_char='-',
+ has_footer=False, footer_char='-',
+ separate_rows=False, row_char='_',
+ delim=' | ', justify=None,
+ prefix='', postfix='', wrapfunc=lambda x:x):
"""Indents a table by column.
- rows: A sequence of sequences of items, one sequence per row.
- - hasHeader: True if the first row consists of the columns' names.
- - headerChar: Character to be used for the row separator line
- (if hasHeader==True or separateRows==True).
+ - has_header: True if the first row consists of the columns' names.
+ - header_char: Character to be used for the row separator line
+ (if has_header==True or separate_rows==True).
- delim: The column delimiter.
- justify: Determines how are data justified in their column.
Valid values are 'left','right' and 'center'.
- - separateRows: True if rows are to be separated by a line
- of 'headerChar's.
+ - separate_rows: True if rows are to be separated by a line
+ of 'header_char's.
- prefix: A string prepended to each printed row.
- postfix: A string appended to each printed row.
- wrapfunc: A function f(text) for wrapping text; each element in
@@ -198,6 +234,7 @@
return [[substr or '' for substr in item] for item in map(None,*newRows)]
# break each logical row into one or more physical ones
logicalRows = [rowWrapper(row) for row in rows]
+ numLogicalRows = len(logicalRows)
# columns of physical rows
columns = map(None,*reduce(operator.add,logicalRows))
numCols = len(columns)
@@ -208,21 +245,37 @@
# get the maximum of each column by the string length of its items
maxWidths = [max([len(str(item)) for item in column]) for column in columns]
- rowSeparator = headerChar * (len(prefix) + len(postfix) + sum(maxWidths) + \
- len(delim)*(len(maxWidths)-1))
+
+ def getSeparator(char, separate):
+ if char is not None and separate:
+ return char * (len(prefix) + len(postfix) + sum(maxWidths) + \
+ len(delim)*(len(maxWidths)-1))
+ else:
+ return None
+
+ header_separator = getSeparator(header_char, has_header)
+ footer_separator = getSeparator(footer_char, has_footer)
+ row_separator = getSeparator(row_char, separate_rows)
+
# select the appropriate justify method
justify_funcs = {'center':str.center, 'right':str.rjust, 'left':str.ljust}
-
output=cStringIO.StringIO()
- if separateRows: print >> output, rowSeparator
- for physicalRows in logicalRows:
+
+ for rowNum, physicalRows in enumerate(logicalRows):
for row in physicalRows:
print >> output, \
prefix \
+ delim.join([justify_funcs[justify[colNum].lower()](str(item),width) for (colNum,item,width) in zip(colNums,row,maxWidths)]) \
+ postfix
- if separateRows or hasHeader: print >> output, rowSeparator; hasHeader=False
+
+ if row_separator and (0 < rowNum < numLogicalRows-2):
+ print >> output, row_separator
+ elif header_separator and rowNum == 0:
+ print >> output, header_separator
+ elif footer_separator and rowNum == numLogicalRows-2:
+ print >> output, footer_separator
+
return output.getvalue()
# written by Mike Brown
More information about the Scipy-svn
mailing list