From 92c51c6de5aa856b64ab5df19d053fa7fe8a489d Mon Sep 17 00:00:00 2001 From: wfr Date: Wed, 25 May 2022 07:33:29 +0200 Subject: [PATCH 01/12] BUG Avoid IndexError on writing empty (row) MI df to excel (GH19543) --- pandas/io/formats/excel.py | 2 +- pandas/tests/io/excel/test_writers.py | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/pandas/io/formats/excel.py b/pandas/io/formats/excel.py index d0fea32cafe26..effb0652aa2d3 100644 --- a/pandas/io/formats/excel.py +++ b/pandas/io/formats/excel.py @@ -634,7 +634,7 @@ def _format_header_regular(self) -> Iterable[ExcelCell]: if self.index: coloffset = 1 if isinstance(self.df.index, MultiIndex): - coloffset = len(self.df.index[0]) + coloffset = len(self.df.index.names) colnames = self.columns if self._has_aliases: diff --git a/pandas/tests/io/excel/test_writers.py b/pandas/tests/io/excel/test_writers.py index 42483645d9fc3..29bc1ce92d4a2 100644 --- a/pandas/tests/io/excel/test_writers.py +++ b/pandas/tests/io/excel/test_writers.py @@ -838,6 +838,22 @@ def test_to_excel_multiindex_no_write_index(self, path): # Test that it is the same as the initial frame. tm.assert_frame_equal(frame1, frame3) + def test_to_excel_empty_multiindex(self, path): + # Test writing and re-reading an empty MI. GH 19543. + + # Initial empty MI frame. + frame1 = DataFrame([[], [], []]).T.set_index([0, 1]) + + # Write out to Excel without the index. + frame1.to_excel(path, "test1") + + # Read it back in. + with ExcelFile(path) as reader: + frame2 = pd.read_excel(reader, sheet_name="test1") + + # Test that it is the same as the initial frame. + tm.assert_frame_equal(frame1, frame2) + def test_to_excel_float_format(self, path): df = DataFrame( [[0.123456, 0.234567, 0.567567], [12.32112, 123123.2, 321321.2]], From 12929ab6148cbf5e6627830ea9b11c925987e483 Mon Sep 17 00:00:00 2001 From: wfr Date: Wed, 25 May 2022 08:18:57 +0200 Subject: [PATCH 02/12] BUG Avoid IndexError on writing empty (row) MI df to excel (GH19543) fix tests, and add changes --- doc/source/whatsnew/v1.5.0.rst | 2 +- pandas/tests/io/excel/test_writers.py | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/doc/source/whatsnew/v1.5.0.rst b/doc/source/whatsnew/v1.5.0.rst index e9e13c3ed5bbe..5f678dd4b23ed 100644 --- a/doc/source/whatsnew/v1.5.0.rst +++ b/doc/source/whatsnew/v1.5.0.rst @@ -813,7 +813,7 @@ I/O - Bug in :func:`read_excel` when reading a ``.ods`` file with newlines between xml elements (:issue:`45598`) - Bug in :func:`read_parquet` when ``engine="fastparquet"`` where the file was not closed on error (:issue:`46555`) - :meth:`to_html` now excludes the ``border`` attribute from ```` elements when ``border`` keyword is set to ``False``. -- +- Bug in :func:`to_excel` when writing an empty dataframe with row :class:`MultiIndex` (:issue:`19543`) Period ^^^^^^ diff --git a/pandas/tests/io/excel/test_writers.py b/pandas/tests/io/excel/test_writers.py index 29bc1ce92d4a2..1e4bb120e3f6f 100644 --- a/pandas/tests/io/excel/test_writers.py +++ b/pandas/tests/io/excel/test_writers.py @@ -841,18 +841,21 @@ def test_to_excel_multiindex_no_write_index(self, path): def test_to_excel_empty_multiindex(self, path): # Test writing and re-reading an empty MI. GH 19543. - # Initial empty MI frame. - frame1 = DataFrame([[], [], []]).T.set_index([0, 1]) + # Initial non-MI frame. + frame1 = DataFrame([[], [], []]).T - # Write out to Excel without the index. - frame1.to_excel(path, "test1") + # Add a MI. + frame2 = frame1.set_index([0, 1]) + + # Write out to Excel. + frame2.to_excel(path, "test1") # Read it back in. with ExcelFile(path) as reader: - frame2 = pd.read_excel(reader, sheet_name="test1") + frame3 = pd.read_excel(reader, sheet_name="test1") # Test that it is the same as the initial frame. - tm.assert_frame_equal(frame1, frame2) + tm.assert_frame_equal(frame1, frame3) def test_to_excel_float_format(self, path): df = DataFrame( From 1a43275832af05533eaba1359a81140a6112c28a Mon Sep 17 00:00:00 2001 From: wfr Date: Wed, 25 May 2022 09:01:51 +0200 Subject: [PATCH 03/12] BUG Avoid IndexError on writing empty (row) MI df to excel (GH19543) fix tests one more time --- pandas/tests/io/excel/test_writers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/tests/io/excel/test_writers.py b/pandas/tests/io/excel/test_writers.py index 1e4bb120e3f6f..5431bca5630f3 100644 --- a/pandas/tests/io/excel/test_writers.py +++ b/pandas/tests/io/excel/test_writers.py @@ -854,8 +854,8 @@ def test_to_excel_empty_multiindex(self, path): with ExcelFile(path) as reader: frame3 = pd.read_excel(reader, sheet_name="test1") - # Test that it is the same as the initial frame. - tm.assert_frame_equal(frame1, frame3) + # Test that it is the same as the initial frame (without index due to empty frame). + tm.assert_frame_equal(frame1, frame3, check_index_type=False) def test_to_excel_float_format(self, path): df = DataFrame( From 6c6a774959105d7b06268e3e445a833bbe01e07b Mon Sep 17 00:00:00 2001 From: wfr Date: Wed, 25 May 2022 09:03:18 +0200 Subject: [PATCH 04/12] BUG Avoid IndexError on writing empty (row) MI df to excel (GH19543) make PEP8 happy --- pandas/tests/io/excel/test_writers.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pandas/tests/io/excel/test_writers.py b/pandas/tests/io/excel/test_writers.py index 5431bca5630f3..e04c6908f6404 100644 --- a/pandas/tests/io/excel/test_writers.py +++ b/pandas/tests/io/excel/test_writers.py @@ -854,7 +854,8 @@ def test_to_excel_empty_multiindex(self, path): with ExcelFile(path) as reader: frame3 = pd.read_excel(reader, sheet_name="test1") - # Test that it is the same as the initial frame (without index due to empty frame). + # Test that it is the same as the initial frame + # (without index due to empty frame). tm.assert_frame_equal(frame1, frame3, check_index_type=False) def test_to_excel_float_format(self, path): From 2a5d71acf2a06ca33e3db38047805b3988bdf287 Mon Sep 17 00:00:00 2001 From: wfr Date: Wed, 25 May 2022 09:03:35 +0200 Subject: [PATCH 05/12] BUG Avoid IndexError on writing empty (row) MI df to excel (GH19543) make PEP8 happy --- pandas/tests/io/excel/test_writers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/io/excel/test_writers.py b/pandas/tests/io/excel/test_writers.py index e04c6908f6404..6e52bea252ae1 100644 --- a/pandas/tests/io/excel/test_writers.py +++ b/pandas/tests/io/excel/test_writers.py @@ -855,7 +855,7 @@ def test_to_excel_empty_multiindex(self, path): frame3 = pd.read_excel(reader, sheet_name="test1") # Test that it is the same as the initial frame - # (without index due to empty frame). + # (do not check index due to empty frame). tm.assert_frame_equal(frame1, frame3, check_index_type=False) def test_to_excel_float_format(self, path): From 1922068f7c8c2c61bb9388466737581fdf9fc675 Mon Sep 17 00:00:00 2001 From: wfr Date: Wed, 25 May 2022 10:02:58 +0200 Subject: [PATCH 06/12] BUG Avoid IndexError on writing empty (row) MI df to excel (GH19543) fix tests one last time --- pandas/tests/io/excel/test_writers.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pandas/tests/io/excel/test_writers.py b/pandas/tests/io/excel/test_writers.py index 6e52bea252ae1..9ac6b5a4a3793 100644 --- a/pandas/tests/io/excel/test_writers.py +++ b/pandas/tests/io/excel/test_writers.py @@ -855,8 +855,9 @@ def test_to_excel_empty_multiindex(self, path): frame3 = pd.read_excel(reader, sheet_name="test1") # Test that it is the same as the initial frame - # (do not check index due to empty frame). - tm.assert_frame_equal(frame1, frame3, check_index_type=False) + # (do not check index and dtype due to empty frame). + tm.assert_frame_equal(frame1, frame3, + check_index_type=False, check_dtype=False) def test_to_excel_float_format(self, path): df = DataFrame( From 2874e2a31060fa2472ba55d030f44a030d6eaf68 Mon Sep 17 00:00:00 2001 From: wfr Date: Wed, 25 May 2022 09:24:18 +0000 Subject: [PATCH 07/12] Fixes from pre-commit [automated commit] --- pandas/tests/io/excel/test_writers.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pandas/tests/io/excel/test_writers.py b/pandas/tests/io/excel/test_writers.py index 9ac6b5a4a3793..766dc2e833685 100644 --- a/pandas/tests/io/excel/test_writers.py +++ b/pandas/tests/io/excel/test_writers.py @@ -856,8 +856,7 @@ def test_to_excel_empty_multiindex(self, path): # Test that it is the same as the initial frame # (do not check index and dtype due to empty frame). - tm.assert_frame_equal(frame1, frame3, - check_index_type=False, check_dtype=False) + tm.assert_frame_equal(frame1, frame3, check_index_type=False, check_dtype=False) def test_to_excel_float_format(self, path): df = DataFrame( From 678b4cf7fc1309f8e400223d90aec3b688678c68 Mon Sep 17 00:00:00 2001 From: wfr Date: Tue, 14 Jun 2022 09:53:49 +0200 Subject: [PATCH 08/12] BUG Avoid IndexError on writing empty (row) MI df to excel (GH19543) requested changes --- doc/source/whatsnew/v1.5.0.rst | 2 +- pandas/tests/io/excel/test_writers.py | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/source/whatsnew/v1.5.0.rst b/doc/source/whatsnew/v1.5.0.rst index 2775234a64716..39cc9bbbc5032 100644 --- a/doc/source/whatsnew/v1.5.0.rst +++ b/doc/source/whatsnew/v1.5.0.rst @@ -832,7 +832,7 @@ I/O - :meth:`to_html` now excludes the ``border`` attribute from ``
`` elements when ``border`` keyword is set to ``False``. - Bug in :func:`read_sas` returned ``None`` rather than an empty DataFrame for SAS7BDAT files with zero rows (:issue:`18198`) - Bug in :class:`StataWriter` where value labels were always written with default encoding (:issue:`46750`) -- Bug in :func:`to_excel` when writing an empty dataframe with row :class:`MultiIndex` (:issue:`19543`) +- Bug in :meth:`to_excel` when writing an empty dataframe with :class:`MultiIndex` (:issue:`19543`) Period ^^^^^^ diff --git a/pandas/tests/io/excel/test_writers.py b/pandas/tests/io/excel/test_writers.py index 766dc2e833685..216cb18c061b4 100644 --- a/pandas/tests/io/excel/test_writers.py +++ b/pandas/tests/io/excel/test_writers.py @@ -839,24 +839,24 @@ def test_to_excel_multiindex_no_write_index(self, path): tm.assert_frame_equal(frame1, frame3) def test_to_excel_empty_multiindex(self, path): - # Test writing and re-reading an empty MI. GH 19543. + # GH 19543. # Initial non-MI frame. - frame1 = DataFrame([[], [], []]).T + expected = DataFrame([], columns=[0, 1, 2]) - # Add a MI. - frame2 = frame1.set_index([0, 1]) + # Frame with empty MI. + df = DataFrame([], index=MultiIndex.from_tuples([], names=[0, 1]), columns=[2]) # Write out to Excel. - frame2.to_excel(path, "test1") + df.to_excel(path, "test1") # Read it back in. with ExcelFile(path) as reader: - frame3 = pd.read_excel(reader, sheet_name="test1") + result = pd.read_excel(reader, sheet_name="test1") # Test that it is the same as the initial frame # (do not check index and dtype due to empty frame). - tm.assert_frame_equal(frame1, frame3, check_index_type=False, check_dtype=False) + tm.assert_frame_equal(result, expected, check_index_type=False, check_dtype=False) def test_to_excel_float_format(self, path): df = DataFrame( From a6a6a8e2e241eb9f5cb13556df89086e518d8837 Mon Sep 17 00:00:00 2001 From: "Wolfgang F. Riedl" Date: Tue, 14 Jun 2022 08:43:20 +0000 Subject: [PATCH 09/12] Fixes from pre-commit [automated commit] --- pandas/tests/io/excel/test_writers.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pandas/tests/io/excel/test_writers.py b/pandas/tests/io/excel/test_writers.py index 216cb18c061b4..b8fcbf7fd99a6 100644 --- a/pandas/tests/io/excel/test_writers.py +++ b/pandas/tests/io/excel/test_writers.py @@ -856,7 +856,9 @@ def test_to_excel_empty_multiindex(self, path): # Test that it is the same as the initial frame # (do not check index and dtype due to empty frame). - tm.assert_frame_equal(result, expected, check_index_type=False, check_dtype=False) + tm.assert_frame_equal( + result, expected, check_index_type=False, check_dtype=False + ) def test_to_excel_float_format(self, path): df = DataFrame( From 006687b89028db4eb3500deeec9359b41fbc66be Mon Sep 17 00:00:00 2001 From: wfr Date: Tue, 14 Jun 2022 11:11:35 +0200 Subject: [PATCH 10/12] BUG Avoid IndexError on writing empty (row) MI df to excel (GH19543) remove comments --- pandas/tests/io/excel/test_writers.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/pandas/tests/io/excel/test_writers.py b/pandas/tests/io/excel/test_writers.py index b8fcbf7fd99a6..26700d7fa8663 100644 --- a/pandas/tests/io/excel/test_writers.py +++ b/pandas/tests/io/excel/test_writers.py @@ -839,23 +839,13 @@ def test_to_excel_multiindex_no_write_index(self, path): tm.assert_frame_equal(frame1, frame3) def test_to_excel_empty_multiindex(self, path): - # GH 19543. - - # Initial non-MI frame. expected = DataFrame([], columns=[0, 1, 2]) - # Frame with empty MI. df = DataFrame([], index=MultiIndex.from_tuples([], names=[0, 1]), columns=[2]) - - # Write out to Excel. df.to_excel(path, "test1") - # Read it back in. with ExcelFile(path) as reader: result = pd.read_excel(reader, sheet_name="test1") - - # Test that it is the same as the initial frame - # (do not check index and dtype due to empty frame). tm.assert_frame_equal( result, expected, check_index_type=False, check_dtype=False ) From 3f78a7d3824ac3dce13846830255179c8981818c Mon Sep 17 00:00:00 2001 From: wfr Date: Tue, 14 Jun 2022 12:26:10 +0200 Subject: [PATCH 11/12] BUG Avoid IndexError on writing empty (row) MI df to excel (GH19543) re-add gh ref --- pandas/tests/io/excel/test_writers.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pandas/tests/io/excel/test_writers.py b/pandas/tests/io/excel/test_writers.py index 26700d7fa8663..ba6366b71d854 100644 --- a/pandas/tests/io/excel/test_writers.py +++ b/pandas/tests/io/excel/test_writers.py @@ -839,6 +839,7 @@ def test_to_excel_multiindex_no_write_index(self, path): tm.assert_frame_equal(frame1, frame3) def test_to_excel_empty_multiindex(self, path): + # GH 19543. expected = DataFrame([], columns=[0, 1, 2]) df = DataFrame([], index=MultiIndex.from_tuples([], names=[0, 1]), columns=[2]) From ee9a56ff484a82d9409f93de62bae2b664b8f09e Mon Sep 17 00:00:00 2001 From: wfr Date: Wed, 15 Jun 2022 07:14:17 +0200 Subject: [PATCH 12/12] BUG Avoid IndexError on writing empty (row) MI df to excel (GH19543) fix changelog entry --- doc/source/whatsnew/v1.5.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.5.0.rst b/doc/source/whatsnew/v1.5.0.rst index 13cf92f530f5e..9fc77a7aaa126 100644 --- a/doc/source/whatsnew/v1.5.0.rst +++ b/doc/source/whatsnew/v1.5.0.rst @@ -872,7 +872,7 @@ I/O - Bug in :func:`read_sas` returned ``None`` rather than an empty DataFrame for SAS7BDAT files with zero rows (:issue:`18198`) - Bug in :class:`StataWriter` where value labels were always written with default encoding (:issue:`46750`) - Bug in :class:`StataWriterUTF8` where some valid characters were removed from variable names (:issue:`47276`) -- Bug in :meth:`to_excel` when writing an empty dataframe with :class:`MultiIndex` (:issue:`19543`) +- Bug in :meth:`DataFrame.to_excel` when writing an empty dataframe with :class:`MultiIndex` (:issue:`19543`) Period ^^^^^^