From e1614aeab338fdcd8ae903c8ac161860c2d9d9f9 Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Sun, 27 Sep 2020 16:51:20 -0500 Subject: [PATCH 01/14] BUG: Don't ignore na_rep in DataFrame.to_html --- pandas/io/formats/format.py | 10 +++++++--- pandas/tests/io/test_html.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index b9d41f142c2b5..e66a14361d3ab 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -1530,12 +1530,16 @@ def format_values_with(float_format): return formatted_values - def _format_strings(self) -> List[str]: + def _format_strings(self) -> np.ndarray: # shortcut if self.formatter is not None: - return [self.formatter(x) for x in self.values] + arr = np.array([self.formatter(x) for x in self.values]) + if self.na_rep is not None: + na_mask = isna(self.values) + arr[na_mask] = self.na_rep + return arr - return list(self.get_result_as_array()) + return self.get_result_as_array() class IntArrayFormatter(GenericArrayFormatter): diff --git a/pandas/tests/io/test_html.py b/pandas/tests/io/test_html.py index 59034e9f3d807..2817fff8ba39b 100644 --- a/pandas/tests/io/test_html.py +++ b/pandas/tests/io/test_html.py @@ -1234,3 +1234,36 @@ def run(self): while helper_thread1.is_alive() or helper_thread2.is_alive(): pass assert None is helper_thread1.err is helper_thread2.err + + def test_to_html_na_rep_and_float_format(self): + # https://github.com/pandas-dev/pandas/issues/13828 + df = DataFrame( + [ + ["A", 1.2225], + ["A", None], + ], + columns=["Group", "Data"], + ) + result = df.to_html(na_rep="Ted", float_format="{:.2f}".format) + expected = """ + + + + + + + + + + + + + + + + + + + +
GroupData
0A1.22
1ATed
""" + assert result == expected From f56d89327189ff0e86769c2fc0416a5722dfb0fc Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Sun, 27 Sep 2020 17:36:18 -0500 Subject: [PATCH 02/14] Back to list --- pandas/io/formats/format.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index e66a14361d3ab..482718a2289aa 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -1530,16 +1530,19 @@ def format_values_with(float_format): return formatted_values - def _format_strings(self) -> np.ndarray: + def _format_strings(self) -> List[str]: # shortcut if self.formatter is not None: - arr = np.array([self.formatter(x) for x in self.values]) - if self.na_rep is not None: + if self.na_rep is None: + return [self.formatter(x) for x in self.values] + else: na_mask = isna(self.values) - arr[na_mask] = self.na_rep - return arr + return [ + self.formatter(x) if not m else self.na_rep + for x, m in zip(self.values, na_mask) + ] - return self.get_result_as_array() + return list(self.get_result_as_array()) class IntArrayFormatter(GenericArrayFormatter): From a240b49a408e8b98bf0c8f68b941f490c59d20d6 Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Tue, 29 Sep 2020 15:19:08 -0500 Subject: [PATCH 03/14] Move test and cover --- pandas/tests/io/formats/test_to_html.py | 35 +++++++++++++++++++++++++ pandas/tests/io/test_html.py | 33 ----------------------- 2 files changed, 35 insertions(+), 33 deletions(-) diff --git a/pandas/tests/io/formats/test_to_html.py b/pandas/tests/io/formats/test_to_html.py index 7acdbfd462874..3f0f743937939 100644 --- a/pandas/tests/io/formats/test_to_html.py +++ b/pandas/tests/io/formats/test_to_html.py @@ -820,3 +820,38 @@ def test_html_repr_min_rows(datapath, max_rows, min_rows, expected): with option_context("display.max_rows", max_rows, "display.min_rows", min_rows): result = df._repr_html_() assert result == expected + + +@pytest.mark.parametrize("na_rep, value", [(None, "nan"), ("Ted", "Ted")]) +def test_to_html_na_rep_and_float_format(na_rep, value): + # https://github.com/pandas-dev/pandas/issues/13828 + df = DataFrame( + [ + ["A", 1.2225], + ["A", None], + ], + columns=["Group", "Data"], + ) + result = df.to_html(na_rep=na_rep, float_format="{:.2f}".format) + expected = f""" + + + + + + + + + + + + + + + + + + + +
GroupData
0A1.22
1A{value}
""" + assert result == expected diff --git a/pandas/tests/io/test_html.py b/pandas/tests/io/test_html.py index 2817fff8ba39b..59034e9f3d807 100644 --- a/pandas/tests/io/test_html.py +++ b/pandas/tests/io/test_html.py @@ -1234,36 +1234,3 @@ def run(self): while helper_thread1.is_alive() or helper_thread2.is_alive(): pass assert None is helper_thread1.err is helper_thread2.err - - def test_to_html_na_rep_and_float_format(self): - # https://github.com/pandas-dev/pandas/issues/13828 - df = DataFrame( - [ - ["A", 1.2225], - ["A", None], - ], - columns=["Group", "Data"], - ) - result = df.to_html(na_rep="Ted", float_format="{:.2f}".format) - expected = """ - - - - - - - - - - - - - - - - - - - -
GroupData
0A1.22
1ATed
""" - assert result == expected From 7ee3ef23e2010084f0575c60cf03cb033ed094f2 Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Tue, 29 Sep 2020 15:30:59 -0500 Subject: [PATCH 04/14] Test for to_latex --- pandas/tests/io/formats/test_to_latex.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/pandas/tests/io/formats/test_to_latex.py b/pandas/tests/io/formats/test_to_latex.py index 7a0d305758802..5a9a08513be80 100644 --- a/pandas/tests/io/formats/test_to_latex.py +++ b/pandas/tests/io/formats/test_to_latex.py @@ -1252,3 +1252,24 @@ def test_get_strrow_multindex_multicolumn(self, row_num, expected): ) assert row_string_converter.get_strrow(row_num=row_num) == expected + + @pytest.mark.parametrize("na_rep, value", [(None, "nan"), ("Ted", "Ted")]) + def test_to_latex_na_rep_and_float_format(self, na_rep, value): + df = DataFrame( + [ + ["A", 1.2225], + ["A", None], + ], + columns=["Group", "Data"], + ) + result = df.to_latex(na_rep=na_rep, float_format="{:.2f}".format) + expected = f"""\\begin{{tabular}}{{llr}} +\\toprule +{{}} & Group & Data \\\\ +\\midrule +0 & A & 1.22 \\\\ +1 & A & {value} \\\\ +\\bottomrule +\\end{{tabular}} +""" + assert result == expected From 72a812a1357d5d07712c0a5ac72f989d6e18becb Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Tue, 29 Sep 2020 15:39:09 -0500 Subject: [PATCH 05/14] More tests --- pandas/tests/io/formats/test_format.py | 11 +++++++++++ pandas/tests/io/formats/test_to_html.py | 6 +++--- pandas/tests/io/formats/test_to_latex.py | 6 +++--- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/pandas/tests/io/formats/test_format.py b/pandas/tests/io/formats/test_format.py index cce0783a3c867..fe40d38ce0adb 100644 --- a/pandas/tests/io/formats/test_format.py +++ b/pandas/tests/io/formats/test_format.py @@ -3425,3 +3425,14 @@ def test_format_remove_leading_space_dataframe(input_array, expected): # GH: 24980 df = pd.DataFrame(input_array).to_string(index=False) assert df == expected + + +@pytest.mark.parametrize("na_rep, string", [(None, "nan"), ("Ted", "Ted")]) +def test_to_string_na_rep_and_float_format(na_rep, string): + # GH 13828 + df = DataFrame([["A", 1.2225], ["A", None]], columns=["Group", "Data"]) + result = df.to_string(na_rep=na_rep, float_format="{:.2f}".format) + expected = f""" Group Data +0 A 1.22 +1 A {string}""" + assert result == expected diff --git a/pandas/tests/io/formats/test_to_html.py b/pandas/tests/io/formats/test_to_html.py index 3f0f743937939..2c2e2d430b419 100644 --- a/pandas/tests/io/formats/test_to_html.py +++ b/pandas/tests/io/formats/test_to_html.py @@ -822,8 +822,8 @@ def test_html_repr_min_rows(datapath, max_rows, min_rows, expected): assert result == expected -@pytest.mark.parametrize("na_rep, value", [(None, "nan"), ("Ted", "Ted")]) -def test_to_html_na_rep_and_float_format(na_rep, value): +@pytest.mark.parametrize("na_rep, string", [(None, "nan"), ("Ted", "Ted")]) +def test_to_html_na_rep_and_float_format(na_rep, string): # https://github.com/pandas-dev/pandas/issues/13828 df = DataFrame( [ @@ -850,7 +850,7 @@ def test_to_html_na_rep_and_float_format(na_rep, value): 1 A - {value} + {string} """ diff --git a/pandas/tests/io/formats/test_to_latex.py b/pandas/tests/io/formats/test_to_latex.py index 5a9a08513be80..49f29cb4f0d09 100644 --- a/pandas/tests/io/formats/test_to_latex.py +++ b/pandas/tests/io/formats/test_to_latex.py @@ -1253,8 +1253,8 @@ def test_get_strrow_multindex_multicolumn(self, row_num, expected): assert row_string_converter.get_strrow(row_num=row_num) == expected - @pytest.mark.parametrize("na_rep, value", [(None, "nan"), ("Ted", "Ted")]) - def test_to_latex_na_rep_and_float_format(self, na_rep, value): + @pytest.mark.parametrize("na_rep, string", [(None, "nan"), ("Ted", "Ted")]) + def test_to_latex_na_rep_and_float_format(self, na_rep, string): df = DataFrame( [ ["A", 1.2225], @@ -1268,7 +1268,7 @@ def test_to_latex_na_rep_and_float_format(self, na_rep, value): {{}} & Group & Data \\\\ \\midrule 0 & A & 1.22 \\\\ -1 & A & {value} \\\\ +1 & A & {string} \\\\ \\bottomrule \\end{{tabular}} """ From ca57e067dbede588a5fa8e130b16eb869979c2b0 Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Tue, 29 Sep 2020 22:47:19 -0500 Subject: [PATCH 06/14] Maybe --- pandas/io/formats/format.py | 2 +- pandas/tests/io/formats/test_format.py | 2 +- pandas/tests/io/formats/test_to_html.py | 2 +- pandas/tests/io/formats/test_to_latex.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index 482718a2289aa..0402792772f4e 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -1533,7 +1533,7 @@ def format_values_with(float_format): def _format_strings(self) -> List[str]: # shortcut if self.formatter is not None: - if self.na_rep is None: + if self.na_rep == "NaN": return [self.formatter(x) for x in self.values] else: na_mask = isna(self.values) diff --git a/pandas/tests/io/formats/test_format.py b/pandas/tests/io/formats/test_format.py index fe40d38ce0adb..d1b196181ae9f 100644 --- a/pandas/tests/io/formats/test_format.py +++ b/pandas/tests/io/formats/test_format.py @@ -3427,7 +3427,7 @@ def test_format_remove_leading_space_dataframe(input_array, expected): assert df == expected -@pytest.mark.parametrize("na_rep, string", [(None, "nan"), ("Ted", "Ted")]) +@pytest.mark.parametrize("na_rep, string", [("NaN", "nan"), ("Ted", "Ted")]) def test_to_string_na_rep_and_float_format(na_rep, string): # GH 13828 df = DataFrame([["A", 1.2225], ["A", None]], columns=["Group", "Data"]) diff --git a/pandas/tests/io/formats/test_to_html.py b/pandas/tests/io/formats/test_to_html.py index 2c2e2d430b419..908b05da02495 100644 --- a/pandas/tests/io/formats/test_to_html.py +++ b/pandas/tests/io/formats/test_to_html.py @@ -822,7 +822,7 @@ def test_html_repr_min_rows(datapath, max_rows, min_rows, expected): assert result == expected -@pytest.mark.parametrize("na_rep, string", [(None, "nan"), ("Ted", "Ted")]) +@pytest.mark.parametrize("na_rep, string", [("NaN", "nan"), ("Ted", "Ted")]) def test_to_html_na_rep_and_float_format(na_rep, string): # https://github.com/pandas-dev/pandas/issues/13828 df = DataFrame( diff --git a/pandas/tests/io/formats/test_to_latex.py b/pandas/tests/io/formats/test_to_latex.py index 49f29cb4f0d09..1628f0e1e7781 100644 --- a/pandas/tests/io/formats/test_to_latex.py +++ b/pandas/tests/io/formats/test_to_latex.py @@ -1253,7 +1253,7 @@ def test_get_strrow_multindex_multicolumn(self, row_num, expected): assert row_string_converter.get_strrow(row_num=row_num) == expected - @pytest.mark.parametrize("na_rep, string", [(None, "nan"), ("Ted", "Ted")]) + @pytest.mark.parametrize("na_rep, string", [("NaN", "nan"), ("Ted", "Ted")]) def test_to_latex_na_rep_and_float_format(self, na_rep, string): df = DataFrame( [ From faa8e2cf07828c5a343702691b690a4438c71e36 Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Thu, 1 Oct 2020 22:17:33 -0500 Subject: [PATCH 07/14] Note --- doc/source/whatsnew/v1.2.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.2.0.rst b/doc/source/whatsnew/v1.2.0.rst index 016e8d90e7d21..8f545d1954746 100644 --- a/doc/source/whatsnew/v1.2.0.rst +++ b/doc/source/whatsnew/v1.2.0.rst @@ -337,7 +337,7 @@ Conversion Strings ^^^^^^^ - Bug in :meth:`Series.to_string`, :meth:`DataFrame.to_string`, and :meth:`DataFrame.to_latex` adding a leading space when ``index=False`` (:issue:`24980`) -- +- Bug in :meth:`DataFrame.to_html`, :meth:`DataFrame.to_string`, and :meth:`DataFrame.to_latex` ignoring the ``na_rep`` argument when ``float_format`` was also specified (:issue:`9046`, :issue:`13828`) - From c81aa047fa1638f9869d2d4af04803f5b1ec65f5 Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Tue, 13 Oct 2020 14:19:30 -0500 Subject: [PATCH 08/14] Refactor --- pandas/io/formats/format.py | 33 ++++++++++-------------- pandas/tests/io/formats/test_format.py | 2 +- pandas/tests/io/formats/test_to_html.py | 2 +- pandas/tests/io/formats/test_to_latex.py | 2 +- 4 files changed, 17 insertions(+), 22 deletions(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index e1555b0af075f..35dc21cbc7e8e 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -1442,8 +1442,20 @@ def get_result_as_array(self) -> np.ndarray: Returns the float values converted into strings using the parameters given at initialisation, as a numpy array """ + + def format_with_na_rep(values, formatter, na_rep): + formatted = np.array(values, dtype="object") + mask = isna(values) + formatted.flat = np.array( + [ + formatter(val) if not m else na_rep + for val, m in zip(values.ravel(), mask.ravel()) + ] + ) + return formatted + if self.formatter is not None: - return np.array([self.formatter(x) for x in self.values]) + return format_with_na_rep(self.values, self.formatter, self.na_rep) if self.fixed_width: threshold = get_option("display.chop_threshold") @@ -1464,13 +1476,7 @@ def format_values_with(float_format): # separate the wheat from the chaff values = self.values is_complex = is_complex_dtype(values) - mask = isna(values) - values = np.array(values, dtype="object") - values[mask] = na_rep - imask = (~mask).ravel() - values.flat[imask] = np.array( - [formatter(val) for val in values.ravel()[imask]] - ) + values = format_with_na_rep(values, formatter, na_rep) if self.fixed_width: if is_complex: @@ -1532,17 +1538,6 @@ def format_values_with(float_format): return formatted_values def _format_strings(self) -> List[str]: - # shortcut - if self.formatter is not None: - if self.na_rep == "NaN": - return [self.formatter(x) for x in self.values] - else: - na_mask = isna(self.values) - return [ - self.formatter(x) if not m else self.na_rep - for x, m in zip(self.values, na_mask) - ] - return list(self.get_result_as_array()) diff --git a/pandas/tests/io/formats/test_format.py b/pandas/tests/io/formats/test_format.py index db4417001cbde..ccda5d1c87e6d 100644 --- a/pandas/tests/io/formats/test_format.py +++ b/pandas/tests/io/formats/test_format.py @@ -3434,7 +3434,7 @@ def test_format_remove_leading_space_dataframe(input_array, expected): assert df == expected -@pytest.mark.parametrize("na_rep, string", [("NaN", "nan"), ("Ted", "Ted")]) +@pytest.mark.parametrize("na_rep, string", [("NaN", "NaN"), ("Ted", "Ted")]) def test_to_string_na_rep_and_float_format(na_rep, string): # GH 13828 df = DataFrame([["A", 1.2225], ["A", None]], columns=["Group", "Data"]) diff --git a/pandas/tests/io/formats/test_to_html.py b/pandas/tests/io/formats/test_to_html.py index 908b05da02495..d6bf54e8078bf 100644 --- a/pandas/tests/io/formats/test_to_html.py +++ b/pandas/tests/io/formats/test_to_html.py @@ -822,7 +822,7 @@ def test_html_repr_min_rows(datapath, max_rows, min_rows, expected): assert result == expected -@pytest.mark.parametrize("na_rep, string", [("NaN", "nan"), ("Ted", "Ted")]) +@pytest.mark.parametrize("na_rep, string", [("NaN", "NaN"), ("Ted", "Ted")]) def test_to_html_na_rep_and_float_format(na_rep, string): # https://github.com/pandas-dev/pandas/issues/13828 df = DataFrame( diff --git a/pandas/tests/io/formats/test_to_latex.py b/pandas/tests/io/formats/test_to_latex.py index cfe6d39c208e8..4428aaf6f15d1 100644 --- a/pandas/tests/io/formats/test_to_latex.py +++ b/pandas/tests/io/formats/test_to_latex.py @@ -1285,7 +1285,7 @@ def test_get_strrow_multindex_multicolumn(self, row_num, expected): assert row_string_converter.get_strrow(row_num=row_num) == expected - @pytest.mark.parametrize("na_rep, string", [("NaN", "nan"), ("Ted", "Ted")]) + @pytest.mark.parametrize("na_rep, string", [("NaN", "NaN"), ("Ted", "Ted")]) def test_to_latex_na_rep_and_float_format(self, na_rep, string): df = DataFrame( [ From 52f16fc6144b812131ec5bba011fbe31b8efdb7e Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Tue, 13 Oct 2020 14:24:05 -0500 Subject: [PATCH 09/14] Move note --- doc/source/whatsnew/v1.2.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.2.0.rst b/doc/source/whatsnew/v1.2.0.rst index 557118defd3b6..af67be0f0c5cd 100644 --- a/doc/source/whatsnew/v1.2.0.rst +++ b/doc/source/whatsnew/v1.2.0.rst @@ -379,7 +379,6 @@ Conversion Strings ^^^^^^^ - Bug in :meth:`Series.to_string`, :meth:`DataFrame.to_string`, and :meth:`DataFrame.to_latex` adding a leading space when ``index=False`` (:issue:`24980`) -- Bug in :meth:`DataFrame.to_html`, :meth:`DataFrame.to_string`, and :meth:`DataFrame.to_latex` ignoring the ``na_rep`` argument when ``float_format`` was also specified (:issue:`9046`, :issue:`13828`) - @@ -430,6 +429,7 @@ I/O - Bug in :func:`read_table` and :func:`read_csv` when ``delim_whitespace=True`` and ``sep=default`` (:issue:`36583`) - Bug in :meth:`to_json` with ``lines=True`` and ``orient='records'`` the last line of the record is not appended with 'new line character' (:issue:`36888`) - Bug in :meth:`read_parquet` with fixed offset timezones. String representation of timezones was not recognized (:issue:`35997`, :issue:`36004`) +- Bug in :meth:`DataFrame.to_html`, :meth:`DataFrame.to_string`, and :meth:`DataFrame.to_latex` ignoring the ``na_rep`` argument when ``float_format`` was also specified (:issue:`9046`, :issue:`13828`) Plotting ^^^^^^^^ From 8c46ab73683ab35ccea0210a35cbc385fe8c3718 Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Tue, 13 Oct 2020 14:53:43 -0500 Subject: [PATCH 10/14] Nothing From 6cb161cc9a544060fbbdfc63df88cde908a675dd Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Tue, 13 Oct 2020 17:47:47 -0500 Subject: [PATCH 11/14] Fixup --- pandas/tests/io/formats/test_format.py | 6 +++--- pandas/tests/io/formats/test_to_html.py | 6 +++--- pandas/tests/io/formats/test_to_latex.py | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pandas/tests/io/formats/test_format.py b/pandas/tests/io/formats/test_format.py index ccda5d1c87e6d..3e3ec84e982ff 100644 --- a/pandas/tests/io/formats/test_format.py +++ b/pandas/tests/io/formats/test_format.py @@ -3434,12 +3434,12 @@ def test_format_remove_leading_space_dataframe(input_array, expected): assert df == expected -@pytest.mark.parametrize("na_rep, string", [("NaN", "NaN"), ("Ted", "Ted")]) -def test_to_string_na_rep_and_float_format(na_rep, string): +@pytest.mark.parametrize("na_rep", ["NaN", "Ted"]) +def test_to_string_na_rep_and_float_format(na_rep): # GH 13828 df = DataFrame([["A", 1.2225], ["A", None]], columns=["Group", "Data"]) result = df.to_string(na_rep=na_rep, float_format="{:.2f}".format) expected = f""" Group Data 0 A 1.22 -1 A {string}""" +1 A {na_rep}""" assert result == expected diff --git a/pandas/tests/io/formats/test_to_html.py b/pandas/tests/io/formats/test_to_html.py index d6bf54e8078bf..b1bff09e7bec3 100644 --- a/pandas/tests/io/formats/test_to_html.py +++ b/pandas/tests/io/formats/test_to_html.py @@ -822,8 +822,8 @@ def test_html_repr_min_rows(datapath, max_rows, min_rows, expected): assert result == expected -@pytest.mark.parametrize("na_rep, string", [("NaN", "NaN"), ("Ted", "Ted")]) -def test_to_html_na_rep_and_float_format(na_rep, string): +@pytest.mark.parametrize("na_rep", ["NaN", "Ted"]) +def test_to_html_na_rep_and_float_format(na_rep): # https://github.com/pandas-dev/pandas/issues/13828 df = DataFrame( [ @@ -850,7 +850,7 @@ def test_to_html_na_rep_and_float_format(na_rep, string): 1 A - {string} + {na_rep} """ diff --git a/pandas/tests/io/formats/test_to_latex.py b/pandas/tests/io/formats/test_to_latex.py index 4428aaf6f15d1..4cdc2625f2e5d 100644 --- a/pandas/tests/io/formats/test_to_latex.py +++ b/pandas/tests/io/formats/test_to_latex.py @@ -1285,8 +1285,8 @@ def test_get_strrow_multindex_multicolumn(self, row_num, expected): assert row_string_converter.get_strrow(row_num=row_num) == expected - @pytest.mark.parametrize("na_rep, string", [("NaN", "NaN"), ("Ted", "Ted")]) - def test_to_latex_na_rep_and_float_format(self, na_rep, string): + @pytest.mark.parametrize("na_rep", ["NaN", "Ted"]) + def test_to_latex_na_rep_and_float_format(self, na_rep): df = DataFrame( [ ["A", 1.2225], @@ -1300,7 +1300,7 @@ def test_to_latex_na_rep_and_float_format(self, na_rep, string): {{}} & Group & Data \\\\ \\midrule 0 & A & 1.22 \\\\ -1 & A & {string} \\\\ +1 & A & {na_rep} \\\\ \\bottomrule \\end{{tabular}} """ From b166ffcbbfb1162b3682492a96ef39e0be136dca Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Tue, 13 Oct 2020 18:10:06 -0500 Subject: [PATCH 12/14] Remove --- pandas/io/formats/format.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index 35dc21cbc7e8e..19f8009bcff71 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -1444,14 +1444,13 @@ def get_result_as_array(self) -> np.ndarray: """ def format_with_na_rep(values, formatter, na_rep): - formatted = np.array(values, dtype="object") mask = isna(values) - formatted.flat = np.array( + formatted = np.array( [ formatter(val) if not m else na_rep for val, m in zip(values.ravel(), mask.ravel()) ] - ) + ).reshape(values.shape) return formatted if self.formatter is not None: From 4b53c91a6df1b15ce16cffa16729c3b7233765d9 Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Sun, 18 Oct 2020 13:00:56 -0500 Subject: [PATCH 13/14] Doc --- pandas/io/formats/format.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index e1fc6a3d2604e..22f62623b840d 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -98,7 +98,7 @@ index : bool, optional, default True Whether to print index (row) labels. na_rep : str, optional, default 'NaN' - String representation of NAN to use. + String representation of ``NaN`` to use. formatters : list, tuple or dict of one-param. functions, optional Formatter functions to apply to columns' elements by position or name. @@ -106,7 +106,12 @@ List/tuple must be of length equal to the number of columns. float_format : one-parameter function, optional, default None Formatter function to apply to columns' elements if they are - floats. The result of this function must be a unicode string. + floats. This function must return a unicode string and will be + applied only to the non-``NaN`` elements, with ``NaN`` being + handled by ``na_rep``. + + .. versionchanged:: 1.2.0 + sparsify : bool, optional, default True Set to False for a DataFrame with a hierarchical index to print every multiindex key at each row. From 8f0ca1583e815eecae347f06f1886fdb4e0da42f Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Tue, 20 Oct 2020 18:37:42 -0500 Subject: [PATCH 14/14] Type --- pandas/io/formats/format.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index 0bea25ed62dc8..3c759f477899b 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -40,6 +40,7 @@ from pandas._libs.tslibs import NaT, Timedelta, Timestamp, iNaT from pandas._libs.tslibs.nattype import NaTType from pandas._typing import ( + ArrayLike, CompressionOptions, FilePathOrBuffer, FloatFormatType, @@ -1370,7 +1371,7 @@ def get_result_as_array(self) -> np.ndarray: the parameters given at initialisation, as a numpy array """ - def format_with_na_rep(values, formatter, na_rep): + def format_with_na_rep(values: ArrayLike, formatter: Callable, na_rep: str): mask = isna(values) formatted = np.array( [