Skip to content

Commit 77713d5

Browse files
simonjayhawkinsjreback
authored andcommitted
to_html formatter not called for float values in a mixed-type column (#25983)
1 parent db2d16a commit 77713d5

File tree

4 files changed

+49
-6
lines changed

4 files changed

+49
-6
lines changed

doc/source/whatsnew/v0.25.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,7 @@ I/O
347347
^^^
348348

349349
- Bug in :func:`DataFrame.to_html()` where values were truncated using display options instead of outputting the full content (:issue:`17004`)
350+
- Bug in :meth:`DataFrame.to_html` that would ignore ``formatters`` argument for float values in a column with ``dtype=object`` (:issue:`13021`)
350351
- Fixed bug in missing text when using :meth:`to_clipboard` if copying utf-16 characters in Python 3 on Windows (:issue:`25040`)
351352
- 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`)
352353
- 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`)

pandas/io/formats/format.py

+11-6
Original file line numberDiff line numberDiff line change
@@ -981,19 +981,24 @@ def _format(x):
981981
if leading_space is None:
982982
leading_space = is_float_type.any()
983983

984+
if leading_space is False:
985+
# False specifically, so that the default is
986+
# to include a space if we get here.
987+
tpl = '{v}'
988+
else:
989+
tpl = ' {v}'
990+
991+
# shortcut
992+
if self.formatter is not None:
993+
return [tpl.format(v=self.formatter(x)) for x in self.values]
994+
984995
fmt_values = []
985996
for i, v in enumerate(vals):
986997
if not is_float_type[i] and leading_space:
987998
fmt_values.append(' {v}'.format(v=_format(v)))
988999
elif is_float_type[i]:
9891000
fmt_values.append(float_format(v))
9901001
else:
991-
if leading_space is False:
992-
# False specifically, so that the default is
993-
# to include a space if we get here.
994-
tpl = '{v}'
995-
else:
996-
tpl = ' {v}'
9971002
fmt_values.append(tpl.format(v=_format(v)))
9981003

9991004
return fmt_values
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<table border="1" class="dataframe">
2+
<thead>
3+
<tr style="text-align: right;">
4+
<th></th>
5+
<th>x</th>
6+
</tr>
7+
</thead>
8+
<tbody>
9+
<tr>
10+
<th>0</th>
11+
<td>a</td>
12+
</tr>
13+
<tr>
14+
<th>1</th>
15+
<td>$0</td>
16+
</tr>
17+
<tr>
18+
<th>2</th>
19+
<td>$10</td>
20+
</tr>
21+
<tr>
22+
<th>3</th>
23+
<td>$3</td>
24+
</tr>
25+
</tbody>
26+
</table>

pandas/tests/io/formats/test_to_html.py

+11
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,17 @@ def test_to_html_invalid_classes_type(classes):
635635
df.to_html(classes=classes)
636636

637637

638+
def test_to_html_formatters_object_type(datapath):
639+
# GH 13021
640+
def f(x):
641+
return x if isinstance(x, str) else '${:,.0f}'.format(x)
642+
643+
df = pd.DataFrame([['a'], [0], [10.4], [3]], columns=['x'])
644+
result = df.to_html(formatters=dict(x=f))
645+
expected = expected_html(datapath, 'gh13021_expected_output')
646+
assert result == expected
647+
648+
638649
def test_to_html_round_column_headers():
639650
# GH 17280
640651
df = DataFrame([1], columns=[0.55555])

0 commit comments

Comments
 (0)