diff --git a/doc/source/whatsnew/v0.24.0.rst b/doc/source/whatsnew/v0.24.0.rst
index 4ff3cc728f7f7..0fad0dc65edaa 100644
--- a/doc/source/whatsnew/v0.24.0.rst
+++ b/doc/source/whatsnew/v0.24.0.rst
@@ -1395,6 +1395,7 @@ Notice how we now instead output ``np.nan`` itself instead of a stringified form
- Bug in :meth:`read_excel()` in which extraneous header names were extracted, even though none were specified (:issue:`11733`)
- Bug in :meth:`read_excel()` in which ``index_col=None`` was not being respected and parsing index columns anyway (:issue:`20480`)
- Bug in :meth:`read_excel()` in which ``usecols`` was not being validated for proper column names when passed in as a string (:issue:`20480`)
+- :func:`DataFrame.to_string()`, :func:`DataFrame.to_html()`, :func:`DataFrame.to_latex()` will correctly format output when a string is passed as the ``float_format`` argument (:issue:`21625`, :issue:`22270`)
Plotting
^^^^^^^^
diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py
index c777b89eeaf12..4c08ee89c33df 100644
--- a/pandas/io/formats/format.py
+++ b/pandas/io/formats/format.py
@@ -960,6 +960,8 @@ def __init__(self, *args, **kwargs):
# float_format is expected to be a string
# formatter should be used to pass a function
if self.float_format is not None and self.formatter is None:
+ # GH21625, GH22270
+ self.fixed_width = False
if callable(self.float_format):
self.formatter = self.float_format
self.float_format = None
diff --git a/pandas/tests/io/formats/data/gh21625_expected_output.html b/pandas/tests/io/formats/data/gh21625_expected_output.html
new file mode 100644
index 0000000000000..a87e4ca301d9d
--- /dev/null
+++ b/pandas/tests/io/formats/data/gh21625_expected_output.html
@@ -0,0 +1,14 @@
+
+
+
+ |
+ x |
+
+
+
+
+ 0 |
+ 0.200 |
+
+
+
\ No newline at end of file
diff --git a/pandas/tests/io/formats/data/gh22270_expected_output.html b/pandas/tests/io/formats/data/gh22270_expected_output.html
new file mode 100644
index 0000000000000..6694c43dc9e68
--- /dev/null
+++ b/pandas/tests/io/formats/data/gh22270_expected_output.html
@@ -0,0 +1,14 @@
+
+
+
+ |
+ x |
+
+
+
+
+ 0 |
+ 100 |
+
+
+
\ No newline at end of file
diff --git a/pandas/tests/io/formats/test_format.py b/pandas/tests/io/formats/test_format.py
index 7d26ea05b514a..b974415ffb029 100644
--- a/pandas/tests/io/formats/test_format.py
+++ b/pandas/tests/io/formats/test_format.py
@@ -1359,6 +1359,18 @@ def test_to_string_float_formatting(self):
'1 2.512000e-01')
assert df_s == expected
+ def test_to_string_float_format_no_fixed_width(self):
+
+ # GH 21625
+ df = DataFrame({'x': [0.19999]})
+ expected = ' x\n0 0.200'
+ assert df.to_string(float_format='%.3f') == expected
+
+ # GH 22270
+ df = DataFrame({'x': [100.0]})
+ expected = ' x\n0 100'
+ assert df.to_string(float_format='%.0f') == expected
+
def test_to_string_small_float_values(self):
df = DataFrame({'a': [1.5, 1e-17, -5.5e-7]})
diff --git a/pandas/tests/io/formats/test_to_html.py b/pandas/tests/io/formats/test_to_html.py
index 0da48f60f1b51..882a629b5b706 100644
--- a/pandas/tests/io/formats/test_to_html.py
+++ b/pandas/tests/io/formats/test_to_html.py
@@ -465,3 +465,15 @@ def test_to_html_with_id(self):
name='myindexname'))
result = df.to_html(index_names=False, table_id="TEST_ID")
assert ' id="TEST_ID"' in result
+
+ def test_to_html_float_format_no_fixed_width(self, datapath):
+
+ # GH 21625
+ df = DataFrame({'x': [0.19999]})
+ expected = expected_html(datapath, 'gh21625_expected_output')
+ assert df.to_html(float_format='%.3f') == expected
+
+ # GH 22270
+ df = DataFrame({'x': [100.0]})
+ expected = expected_html(datapath, 'gh22270_expected_output')
+ assert df.to_html(float_format='%.0f') == expected
diff --git a/pandas/tests/io/formats/test_to_latex.py b/pandas/tests/io/formats/test_to_latex.py
index 73517890565c7..f55fa289ea085 100644
--- a/pandas/tests/io/formats/test_to_latex.py
+++ b/pandas/tests/io/formats/test_to_latex.py
@@ -708,3 +708,29 @@ def test_to_latex_multiindex_empty_name(self):
\end{tabular}
"""
assert observed == expected
+
+ def test_to_latex_float_format_no_fixed_width(self):
+
+ # GH 21625
+ df = DataFrame({'x': [0.19999]})
+ expected = r"""\begin{tabular}{lr}
+\toprule
+{} & x \\
+\midrule
+0 & 0.200 \\
+\bottomrule
+\end{tabular}
+"""
+ assert df.to_latex(float_format='%.3f') == expected
+
+ # GH 22270
+ df = DataFrame({'x': [100.0]})
+ expected = r"""\begin{tabular}{lr}
+\toprule
+{} & x \\
+\midrule
+0 & 100 \\
+\bottomrule
+\end{tabular}
+"""
+ assert df.to_latex(float_format='%.0f') == expected