diff --git a/doc/source/whatsnew/v0.25.0.rst b/doc/source/whatsnew/v0.25.0.rst index 679a374b9b117..fe379c5e61457 100644 --- a/doc/source/whatsnew/v0.25.0.rst +++ b/doc/source/whatsnew/v0.25.0.rst @@ -345,6 +345,7 @@ I/O ^^^ - Bug in :func:`DataFrame.to_html()` where values were truncated using display options instead of outputting the full content (:issue:`17004`) +- Bug in :meth:`DataFrame.to_html` that would ignore ``formatters`` argument for float values in a column with ``dtype=object`` (:issue:`13021`) - Fixed bug in missing text when using :meth:`to_clipboard` if copying utf-16 characters in Python 3 on Windows (:issue:`25040`) - Bug in :func:`read_json` for ``orient='table'`` when it tries to infer dtypes by default, which is not applicable as dtypes are already defined in the JSON schema (:issue:`21345`) - Bug in :func:`read_json` for ``orient='table'`` and float index, as it infers index dtype by default, which is not applicable because index dtype is already defined in the JSON schema (:issue:`25433`) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index b397a370cecbf..e8fcae809f1d6 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -981,6 +981,17 @@ def _format(x): if leading_space is None: leading_space = is_float_type.any() + if leading_space is False: + # False specifically, so that the default is + # to include a space if we get here. + tpl = '{v}' + else: + tpl = ' {v}' + + # shortcut + if self.formatter is not None: + return [tpl.format(v=self.formatter(x)) for x in self.values] + fmt_values = [] for i, v in enumerate(vals): if not is_float_type[i] and leading_space: @@ -988,12 +999,6 @@ def _format(x): elif is_float_type[i]: fmt_values.append(float_format(v)) else: - if leading_space is False: - # False specifically, so that the default is - # to include a space if we get here. - tpl = '{v}' - else: - tpl = ' {v}' fmt_values.append(tpl.format(v=_format(v))) return fmt_values diff --git a/pandas/tests/io/formats/data/html/gh13021_expected_output.html b/pandas/tests/io/formats/data/html/gh13021_expected_output.html new file mode 100644 index 0000000000000..55d864d8a0d3d --- /dev/null +++ b/pandas/tests/io/formats/data/html/gh13021_expected_output.html @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +
x
0a
1$0
2$10
3$3
diff --git a/pandas/tests/io/formats/test_to_html.py b/pandas/tests/io/formats/test_to_html.py index 0acad80bbeef2..3b36c9c785244 100644 --- a/pandas/tests/io/formats/test_to_html.py +++ b/pandas/tests/io/formats/test_to_html.py @@ -635,6 +635,17 @@ def test_to_html_invalid_classes_type(classes): df.to_html(classes=classes) +def test_to_html_formatters_object_type(datapath): + # GH 13021 + def f(x): + return x if isinstance(x, str) else '${:,.0f}'.format(x) + + df = pd.DataFrame([['a'], [0], [10.4], [3]], columns=['x']) + result = df.to_html(formatters=dict(x=f)) + expected = expected_html(datapath, 'gh13021_expected_output') + assert result == expected + + def test_to_html_round_column_headers(): # GH 17280 df = DataFrame([1], columns=[0.55555])