diff --git a/pandas/core/format.py b/pandas/core/format.py index 29f1e1efe9f5d..40adb41e8554e 100644 --- a/pandas/core/format.py +++ b/pandas/core/format.py @@ -684,7 +684,8 @@ def _format_col(self, i): return format_array( frame.iloc[:, i]._values, formatter, float_format=self.float_format, na_rep=self.na_rep, - space=self.col_space + space=self.col_space, + justify=getattr(formatter,'justify','right') ) def to_html(self, classes=None, notebook=False): @@ -820,7 +821,8 @@ def __init__(self, formatter, classes=None, max_rows=None, max_cols=None, self.elements = [] self.bold_rows = self.fmt.kwds.get('bold_rows', False) self.escape = self.fmt.kwds.get('escape', True) - + if self.fmt.formatters is not None and len(self.fmt.formatters): + self.escape = tuple(getattr(f,'escape',self.escape) for f in self.fmt.formatters) self.max_rows = max_rows or len(self.fmt.frame) self.max_cols = max_cols or len(self.fmt.columns) self.show_dimensions = self.fmt.show_dimensions @@ -840,16 +842,16 @@ def write_th(self, s, indent=0, tags=None): return self._write_cell(s, kind='th', indent=indent, tags=tags) - def write_td(self, s, indent=0, tags=None): - return self._write_cell(s, kind='td', indent=indent, tags=tags) + def write_td(self, s, indent=0, tags=None,column=None): + return self._write_cell(s, kind='td', indent=indent, tags=tags, column=column) - def _write_cell(self, s, kind='td', indent=0, tags=None): + def _write_cell(self, s, kind='td', indent=0, tags=None, column=None): if tags is not None: start_tag = '<%s %s>' % (kind, tags) else: start_tag = '<%s>' % kind - - if self.escape: + + if (self.escape if column is None or not isinstance(self.escape, tuple) else self.escape[column]): # escape & first to prevent double escaping of & esc = OrderedDict( [('&', r'&'), ('<', r'<'), ('>', r'>')] @@ -861,7 +863,7 @@ def _write_cell(self, s, kind='td', indent=0, tags=None): '%s%s' % (start_tag, rs, kind), indent) def write_tr(self, line, indent=0, indent_delta=4, header=False, - align=None, tags=None, nindex_levels=0): + align=None, tags=None, nindex_levels=0, escape=None): if tags is None: tags = {} @@ -876,7 +878,7 @@ def write_tr(self, line, indent=0, indent_delta=4, header=False, if header or (self.bold_rows and i < nindex_levels): self.write_th(s, indent, tags=val_tag) else: - self.write_td(s, indent, tags=val_tag) + self.write_td(s, indent, tags=val_tag, column=i-nindex_levels) indent -= indent_delta self.write('', indent) diff --git a/pandas/core/frame.py b/pandas/core/frame.py index e81aaebe77807..7588fc2c62860 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -1468,7 +1468,14 @@ def to_html(self, buf=None, columns=None, col_space=None, colSpace=None, max_cols : int, optional Maximum number of columns to show before truncating. If None, show all. - + formatters : callabable or dict/list/tuple of callables, optional + The keys to the dict are the column names, any missing or additional + names will be given defaults or ignored respectively. If list/tuple + the length should match the columns exactly. + Each callable can have an optional boolean `escape` attribute, + and an optional string `justify` attribute. See `_make_fixed_width` + function in `format.py` for meaning of `justify`. If `escape` is + not provided the primary `escape` argument is used (see above). """ if colSpace is not None: # pragma: no cover @@ -1476,6 +1483,23 @@ def to_html(self, buf=None, columns=None, col_space=None, colSpace=None, FutureWarning, stacklevel=2) col_space = colSpace + # convert dict/single callable to list + if isinstance(formatters,dict): + formatters_list = [] + for cname in self.columns: + if cname in formatters: + formatters_list.append(formatters[cname]) + elif isinstance(cname,tuple): + # look through all the names in tuple and take the first + # matching name form the supplied formatters + formatters_list.append(next((formatters[n] for n in cname\ + if n in formatters),None)) + else: + formatters_list.append(None) + formatters = tuple(formatters_list) + elif callable(formatters): + formatters = (formatters,)*len(self.columns) + formatter = fmt.DataFrameFormatter(self, buf=buf, columns=columns, col_space=col_space, na_rep=na_rep, formatters=formatters,