From d1d0565e279fcc83e381faef1428c4d4d282c3c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matias=20Heikkil=C3=A4?= Date: Sun, 12 May 2019 12:13:03 +0300 Subject: [PATCH] BUG: Fix MultiIndex DataFrame to_csv() segfault (#26303) --- doc/source/whatsnew/v0.25.0.rst | 2 +- pandas/core/indexes/multi.py | 4 +++- pandas/tests/frame/test_to_csv.py | 9 +++++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/doc/source/whatsnew/v0.25.0.rst b/doc/source/whatsnew/v0.25.0.rst index e0b4baf5d8543..990489042de3c 100644 --- a/doc/source/whatsnew/v0.25.0.rst +++ b/doc/source/whatsnew/v0.25.0.rst @@ -336,7 +336,7 @@ Indexing - Improved exception message when calling :meth:`DataFrame.iloc` with a list of non-numeric objects (:issue:`25753`). - Bug in :meth:`DataFrame.loc` and :meth:`Series.loc` where ``KeyError`` was not raised for a ``MultiIndex`` when the key was less than or equal to the number of levels in the :class:`MultiIndex` (:issue:`14885`). - Bug in which :meth:`DataFrame.append` produced an erroneous warning indicating that a ``KeyError`` will be thrown in the future when the data to be appended contains new columns (:issue:`22252`). -- +- Bug in which :meth:`DataFrame.to_csv` caused a segfault for a reindexed data frame, when the indices were single-level :class:`MultiIndex` (:issue:`26303`). Missing diff --git a/pandas/core/indexes/multi.py b/pandas/core/indexes/multi.py index ff670e5524dc7..6a1574872f5f6 100644 --- a/pandas/core/indexes/multi.py +++ b/pandas/core/indexes/multi.py @@ -946,7 +946,9 @@ def _format_native_types(self, na_rep='nan', **kwargs): new_codes.append(level_codes) if len(new_levels) == 1: - return Index(new_levels[0])._format_native_types() + # a single-level multi-index + return Index(new_levels[0].take( + new_codes[0]))._format_native_types() else: # reconstruct the multi-index mi = MultiIndex(levels=new_levels, codes=new_codes, diff --git a/pandas/tests/frame/test_to_csv.py b/pandas/tests/frame/test_to_csv.py index 20cd8c9dc744a..7bc03264c3a39 100644 --- a/pandas/tests/frame/test_to_csv.py +++ b/pandas/tests/frame/test_to_csv.py @@ -1220,6 +1220,15 @@ def test_multi_index_header(self): expected = tm.convert_rows_list_to_csv_str(expected_rows) assert result == expected + def test_to_csv_single_level_multi_index(self): + # see gh-26303 + index = pd.Index([(1,), (2,), (3,)]) + df = pd.DataFrame([[1, 2, 3]], columns=index) + df = df.reindex(columns=[(1,), (3,)]) + expected = ",1,3\n0,1,3\n" + result = df.to_csv(line_terminator='\n') + assert_almost_equal(result, expected) + def test_gz_lineend(self): # GH 25311 df = pd.DataFrame({'a': [1, 2]})