From a92c29ce6ce4ea662469e90a45d2d2138bc789ed Mon Sep 17 00:00:00 2001 From: thoo Date: Thu, 14 Feb 2019 23:25:28 -0500 Subject: [PATCH 01/16] DataFrame.pivot to support multiple columns as index --- doc/source/whatsnew/v0.25.0.rst | 2 +- pandas/core/reshape/pivot.py | 18 ++++++++++++++++-- pandas/tests/reshape/test_pivot.py | 28 ++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/doc/source/whatsnew/v0.25.0.rst b/doc/source/whatsnew/v0.25.0.rst index 95362521f3b9f..804d00d3a0f7c 100644 --- a/doc/source/whatsnew/v0.25.0.rst +++ b/doc/source/whatsnew/v0.25.0.rst @@ -20,7 +20,7 @@ Other Enhancements ^^^^^^^^^^^^^^^^^^ - :meth:`Timestamp.replace` now supports the ``fold`` argument to disambiguate DST transition times (:issue:`25017`) -- +- :meth:`DataFrame.pivot` now supports multiple columns to be set as index. - .. _whatsnew_0250.api_breaking: diff --git a/pandas/core/reshape/pivot.py b/pandas/core/reshape/pivot.py index 54f11646fc753..109871a80e721 100644 --- a/pandas/core/reshape/pivot.py +++ b/pandas/core/reshape/pivot.py @@ -368,15 +368,29 @@ def _convert_by(by): @Appender(_shared_docs['pivot'], indents=1) def pivot(data, index=None, columns=None, values=None): if values is None: - cols = [columns] if index is None else [index, columns] + if index is None: + cols = [columns] + else: + if is_list_like(index): + cols = [ column for column in index] + else: + cols = [index] + cols.append(columns) append = index is None indexed = data.set_index(cols, append=append) + else: if index is None: index = data.index + index = MultiIndex.from_arrays([index, data[columns]]) + elif is_list_like(index): + # Iterating through the list of multiple columns of an index + indexes = [data[column] for column in index] + indexes.append(data[columns]) + index = MultiIndex.from_arrays(indexes) else: index = data[index] - index = MultiIndex.from_arrays([index, data[columns]]) + index = MultiIndex.from_arrays([index, data[columns]]) if is_list_like(values) and not isinstance(values, tuple): # Exclude tuple because it is seen as a single column name diff --git a/pandas/tests/reshape/test_pivot.py b/pandas/tests/reshape/test_pivot.py index e4fbb204af533..f627f20710966 100644 --- a/pandas/tests/reshape/test_pivot.py +++ b/pandas/tests/reshape/test_pivot.py @@ -301,6 +301,34 @@ def test_pivot_multi_functions(self): expected = concat([means, stds], keys=['mean', 'std'], axis=1) tm.assert_frame_equal(result, expected) + def test_pivot_multiple_columns_as_index(self): + # adding the test case for multiple columns as index (#21425) + df = DataFrame({'lev1': [1, 1, 1, 1, 2, 2, 2, 2], + 'lev2': [1, 1, 2, 2, 1, 1, 2, 2], + 'lev3': [1, 2, 1, 2, 1, 2, 1, 2], + 'values': [0, 1, 2, 3, 4, 5, 6, 7]}) + result = df.pivot(index=['lev1', 'lev2'], + columns='lev3', + values='values') + result_no_values = df.pivot(index=['lev1', 'lev2'], + columns='lev3') + data = [[0, 1], [2, 3], [4, 5], [6, 7]] + exp_index = pd.MultiIndex.from_product([[1, 2], [1, 2]], + names=['lev1', 'lev2']) + exp_columns_1 = Index([1, 2], name='lev3') + expected_1 = DataFrame(data=data, index=exp_index, + columns=exp_columns_1) + + exp_columns_2 = MultiIndex(levels=[['values'], [1, 2]], + labels=[[0, 0], [0, 1]], + names=[None, 'lev3']) + + expected_2 = DataFrame(data=data, index=exp_index, + columns=exp_columns_2) + + tm.assert_frame_equal(result, expected_1) + tm.assert_frame_equal(result_no_values, expected_2) + @pytest.mark.parametrize('method', [True, False]) def test_pivot_index_with_nan(self, method): # GH 3588 From 08650a288160ab34933b18fce07abbb0edd8fd4d Mon Sep 17 00:00:00 2001 From: thoo Date: Thu, 14 Feb 2019 23:37:39 -0500 Subject: [PATCH 02/16] fix flake8 --- pandas/core/reshape/pivot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/reshape/pivot.py b/pandas/core/reshape/pivot.py index 109871a80e721..0b5d053c9fbf1 100644 --- a/pandas/core/reshape/pivot.py +++ b/pandas/core/reshape/pivot.py @@ -372,7 +372,7 @@ def pivot(data, index=None, columns=None, values=None): cols = [columns] else: if is_list_like(index): - cols = [ column for column in index] + cols = [column for column in index] else: cols = [index] cols.append(columns) From c6dddf26d2bae29be6ca76a196902080c2ad8102 Mon Sep 17 00:00:00 2001 From: thoo Date: Thu, 14 Feb 2019 23:45:17 -0500 Subject: [PATCH 03/16] update whatsnew --- doc/source/whatsnew/v0.25.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v0.25.0.rst b/doc/source/whatsnew/v0.25.0.rst index 804d00d3a0f7c..463017b3f54d0 100644 --- a/doc/source/whatsnew/v0.25.0.rst +++ b/doc/source/whatsnew/v0.25.0.rst @@ -20,7 +20,7 @@ Other Enhancements ^^^^^^^^^^^^^^^^^^ - :meth:`Timestamp.replace` now supports the ``fold`` argument to disambiguate DST transition times (:issue:`25017`) -- :meth:`DataFrame.pivot` now supports multiple columns to be set as index. +- :meth:`DataFrame.pivot` now supports multiple indexs. - .. _whatsnew_0250.api_breaking: From b3dad898085af0e66bb997c13d565252dfa3a34d Mon Sep 17 00:00:00 2001 From: thoo Date: Fri, 15 Feb 2019 00:29:29 -0500 Subject: [PATCH 04/16] Fix future_warning --- pandas/tests/reshape/test_pivot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/reshape/test_pivot.py b/pandas/tests/reshape/test_pivot.py index f627f20710966..242d471a289d8 100644 --- a/pandas/tests/reshape/test_pivot.py +++ b/pandas/tests/reshape/test_pivot.py @@ -320,7 +320,7 @@ def test_pivot_multiple_columns_as_index(self): columns=exp_columns_1) exp_columns_2 = MultiIndex(levels=[['values'], [1, 2]], - labels=[[0, 0], [0, 1]], + codes=[[0, 0], [0, 1]], names=[None, 'lev3']) expected_2 = DataFrame(data=data, index=exp_index, From def0e2db81131221798c3b1d134cde813200e2b3 Mon Sep 17 00:00:00 2001 From: thoo Date: Sat, 16 Feb 2019 14:25:52 -0500 Subject: [PATCH 05/16] Fix based on suggestions --- doc/source/whatsnew/v0.25.0.rst | 2 +- pandas/core/reshape/pivot.py | 12 ++++++---- pandas/tests/reshape/test_pivot.py | 38 +++++++++++++++++------------- 3 files changed, 29 insertions(+), 23 deletions(-) diff --git a/doc/source/whatsnew/v0.25.0.rst b/doc/source/whatsnew/v0.25.0.rst index 463017b3f54d0..965fa1a0a0906 100644 --- a/doc/source/whatsnew/v0.25.0.rst +++ b/doc/source/whatsnew/v0.25.0.rst @@ -20,7 +20,7 @@ Other Enhancements ^^^^^^^^^^^^^^^^^^ - :meth:`Timestamp.replace` now supports the ``fold`` argument to disambiguate DST transition times (:issue:`25017`) -- :meth:`DataFrame.pivot` now supports multiple indexs. +- :meth:`DataFrame.pivot` now supports multiple column indexes (:issue:`21425`) - .. _whatsnew_0250.api_breaking: diff --git a/pandas/core/reshape/pivot.py b/pandas/core/reshape/pivot.py index 0b5d053c9fbf1..7af2a75adec66 100644 --- a/pandas/core/reshape/pivot.py +++ b/pandas/core/reshape/pivot.py @@ -372,8 +372,10 @@ def pivot(data, index=None, columns=None, values=None): cols = [columns] else: if is_list_like(index): - cols = [column for column in index] + # If a given index is a list, set cols to index. + cols = index else: + # If a given index is not a list, set cols to a list of index. cols = [index] cols.append(columns) append = index is None @@ -381,19 +383,19 @@ def pivot(data, index=None, columns=None, values=None): else: if index is None: - index = data.index - index = MultiIndex.from_arrays([index, data[columns]]) + index = MultiIndex.from_arrays([data.index, data[columns]]) elif is_list_like(index): - # Iterating through the list of multiple columns of an index + # Iterating through the list of multiple columns of an index. indexes = [data[column] for column in index] indexes.append(data[columns]) index = MultiIndex.from_arrays(indexes) else: + # Build multi-indexes if index is not None and not a list. index = data[index] index = MultiIndex.from_arrays([index, data[columns]]) if is_list_like(values) and not isinstance(values, tuple): - # Exclude tuple because it is seen as a single column name + # Exclude tuple because it is seen as a single column name. indexed = data._constructor(data[values].values, index=index, columns=values) else: diff --git a/pandas/tests/reshape/test_pivot.py b/pandas/tests/reshape/test_pivot.py index 242d471a289d8..eddfa7dc72a1d 100644 --- a/pandas/tests/reshape/test_pivot.py +++ b/pandas/tests/reshape/test_pivot.py @@ -301,33 +301,37 @@ def test_pivot_multi_functions(self): expected = concat([means, stds], keys=['mean', 'std'], axis=1) tm.assert_frame_equal(result, expected) - def test_pivot_multiple_columns_as_index(self): + @pytest.mark.parametrize('method', [True, False]) + def test_pivot_multiple_columns_as_index(self, method): # adding the test case for multiple columns as index (#21425) df = DataFrame({'lev1': [1, 1, 1, 1, 2, 2, 2, 2], 'lev2': [1, 1, 2, 2, 1, 1, 2, 2], 'lev3': [1, 2, 1, 2, 1, 2, 1, 2], 'values': [0, 1, 2, 3, 4, 5, 6, 7]}) - result = df.pivot(index=['lev1', 'lev2'], - columns='lev3', - values='values') - result_no_values = df.pivot(index=['lev1', 'lev2'], - columns='lev3') data = [[0, 1], [2, 3], [4, 5], [6, 7]] exp_index = pd.MultiIndex.from_product([[1, 2], [1, 2]], - names=['lev1', 'lev2']) - exp_columns_1 = Index([1, 2], name='lev3') - expected_1 = DataFrame(data=data, index=exp_index, - columns=exp_columns_1) + names=['lev1', 'lev2']) + if method: + result = df.pivot(index=['lev1', 'lev2'], + columns='lev3', + values='values') + + exp_columns_1 = Index([1, 2], name='lev3') + expected = DataFrame(data=data, index=exp_index, + columns=exp_columns_1) + + else: + result = df.pivot(index=['lev1', 'lev2'], + columns='lev3') - exp_columns_2 = MultiIndex(levels=[['values'], [1, 2]], - codes=[[0, 0], [0, 1]], - names=[None, 'lev3']) + exp_columns_2 = MultiIndex(levels=[['values'], [1, 2]], + codes=[[0, 0], [0, 1]], + names=[None, 'lev3']) - expected_2 = DataFrame(data=data, index=exp_index, - columns=exp_columns_2) + expected = DataFrame(data=data, index=exp_index, + columns=exp_columns_2) - tm.assert_frame_equal(result, expected_1) - tm.assert_frame_equal(result_no_values, expected_2) + tm.assert_frame_equal(result,expected) @pytest.mark.parametrize('method', [True, False]) def test_pivot_index_with_nan(self, method): From 621514655e45e2b3b05416667d127e0bc7bb6d01 Mon Sep 17 00:00:00 2001 From: thoo Date: Sat, 16 Feb 2019 14:28:25 -0500 Subject: [PATCH 06/16] fix flake8 --- pandas/tests/reshape/test_pivot.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/pandas/tests/reshape/test_pivot.py b/pandas/tests/reshape/test_pivot.py index eddfa7dc72a1d..33f55798ab153 100644 --- a/pandas/tests/reshape/test_pivot.py +++ b/pandas/tests/reshape/test_pivot.py @@ -310,28 +310,28 @@ def test_pivot_multiple_columns_as_index(self, method): 'values': [0, 1, 2, 3, 4, 5, 6, 7]}) data = [[0, 1], [2, 3], [4, 5], [6, 7]] exp_index = pd.MultiIndex.from_product([[1, 2], [1, 2]], - names=['lev1', 'lev2']) + names=['lev1', 'lev2']) if method: result = df.pivot(index=['lev1', 'lev2'], - columns='lev3', - values='values') + columns='lev3', + values='values') exp_columns_1 = Index([1, 2], name='lev3') expected = DataFrame(data=data, index=exp_index, - columns=exp_columns_1) + columns=exp_columns_1) else: result = df.pivot(index=['lev1', 'lev2'], - columns='lev3') + columns='lev3') exp_columns_2 = MultiIndex(levels=[['values'], [1, 2]], - codes=[[0, 0], [0, 1]], - names=[None, 'lev3']) + codes=[[0, 0], [0, 1]], + names=[None, 'lev3']) expected = DataFrame(data=data, index=exp_index, - columns=exp_columns_2) + columns=exp_columns_2) - tm.assert_frame_equal(result,expected) + tm.assert_frame_equal(result, expected) @pytest.mark.parametrize('method', [True, False]) def test_pivot_index_with_nan(self, method): From 565c41c8b8894361e86e9013f5a14b3102dd4520 Mon Sep 17 00:00:00 2001 From: thoo Date: Sat, 16 Feb 2019 14:30:01 -0500 Subject: [PATCH 07/16] Add more comments --- pandas/core/reshape/pivot.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pandas/core/reshape/pivot.py b/pandas/core/reshape/pivot.py index 7af2a75adec66..8184e8847f9ca 100644 --- a/pandas/core/reshape/pivot.py +++ b/pandas/core/reshape/pivot.py @@ -369,6 +369,7 @@ def _convert_by(by): def pivot(data, index=None, columns=None, values=None): if values is None: if index is None: + # Build cols for indexes. cols = [columns] else: if is_list_like(index): From d795e862230bbae15babfafbea1bddd83ebf90fe Mon Sep 17 00:00:00 2001 From: thoo Date: Sat, 16 Feb 2019 14:37:31 -0500 Subject: [PATCH 08/16] refactor pytest --- pandas/tests/reshape/test_pivot.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/pandas/tests/reshape/test_pivot.py b/pandas/tests/reshape/test_pivot.py index 33f55798ab153..fa9356c277749 100644 --- a/pandas/tests/reshape/test_pivot.py +++ b/pandas/tests/reshape/test_pivot.py @@ -315,22 +315,17 @@ def test_pivot_multiple_columns_as_index(self, method): result = df.pivot(index=['lev1', 'lev2'], columns='lev3', values='values') - - exp_columns_1 = Index([1, 2], name='lev3') - expected = DataFrame(data=data, index=exp_index, - columns=exp_columns_1) + exp_columns = Index([1, 2], name='lev3') else: result = df.pivot(index=['lev1', 'lev2'], columns='lev3') - - exp_columns_2 = MultiIndex(levels=[['values'], [1, 2]], + exp_columns = MultiIndex(levels=[['values'], [1, 2]], codes=[[0, 0], [0, 1]], names=[None, 'lev3']) - expected = DataFrame(data=data, index=exp_index, - columns=exp_columns_2) - + expected = DataFrame(data=data, index=exp_index, + columns=exp_columns) tm.assert_frame_equal(result, expected) @pytest.mark.parametrize('method', [True, False]) From 0a6e4be41a4d1a0a7c9c9f2ca998f785c20b8bc1 Mon Sep 17 00:00:00 2001 From: thoo Date: Sat, 16 Feb 2019 14:42:25 -0500 Subject: [PATCH 09/16] change comments --- pandas/core/reshape/pivot.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pandas/core/reshape/pivot.py b/pandas/core/reshape/pivot.py index 8184e8847f9ca..46ac7d0f4f393 100644 --- a/pandas/core/reshape/pivot.py +++ b/pandas/core/reshape/pivot.py @@ -372,11 +372,10 @@ def pivot(data, index=None, columns=None, values=None): # Build cols for indexes. cols = [columns] else: + # Accept multiple column indexes. if is_list_like(index): - # If a given index is a list, set cols to index. cols = index else: - # If a given index is not a list, set cols to a list of index. cols = [index] cols.append(columns) append = index is None From ad4a761c1210fec379edba113ccdae940f30e0b9 Mon Sep 17 00:00:00 2001 From: thoo Date: Sat, 16 Feb 2019 14:52:41 -0500 Subject: [PATCH 10/16] fix if/else --- pandas/core/reshape/pivot.py | 15 ++++++--------- pandas/tests/reshape/test_pivot.py | 6 +++--- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/pandas/core/reshape/pivot.py b/pandas/core/reshape/pivot.py index 46ac7d0f4f393..5139ebbf85a4a 100644 --- a/pandas/core/reshape/pivot.py +++ b/pandas/core/reshape/pivot.py @@ -368,16 +368,13 @@ def _convert_by(by): @Appender(_shared_docs['pivot'], indents=1) def pivot(data, index=None, columns=None, values=None): if values is None: - if index is None: - # Build cols for indexes. - cols = [columns] + cols = [] + # Make acceptable for multiple column indexes. + if is_list_like(index): + cols.extend(index) else: - # Accept multiple column indexes. - if is_list_like(index): - cols = index - else: - cols = [index] - cols.append(columns) + cols.append(index) + cols.append(columns) append = index is None indexed = data.set_index(cols, append=append) diff --git a/pandas/tests/reshape/test_pivot.py b/pandas/tests/reshape/test_pivot.py index fa9356c277749..a897f6465c811 100644 --- a/pandas/tests/reshape/test_pivot.py +++ b/pandas/tests/reshape/test_pivot.py @@ -321,11 +321,11 @@ def test_pivot_multiple_columns_as_index(self, method): result = df.pivot(index=['lev1', 'lev2'], columns='lev3') exp_columns = MultiIndex(levels=[['values'], [1, 2]], - codes=[[0, 0], [0, 1]], - names=[None, 'lev3']) + codes=[[0, 0], [0, 1]], + names=[None, 'lev3']) expected = DataFrame(data=data, index=exp_index, - columns=exp_columns) + columns=exp_columns) tm.assert_frame_equal(result, expected) @pytest.mark.parametrize('method', [True, False]) From 2e5dd67f20ba64df12a29dc174e82673d7605905 Mon Sep 17 00:00:00 2001 From: thoo Date: Sat, 16 Feb 2019 17:33:09 -0500 Subject: [PATCH 11/16] fix failing tests --- pandas/core/reshape/pivot.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/pandas/core/reshape/pivot.py b/pandas/core/reshape/pivot.py index d2a8c4d56bd6c..4fa07665c92f9 100644 --- a/pandas/core/reshape/pivot.py +++ b/pandas/core/reshape/pivot.py @@ -368,13 +368,22 @@ def _convert_by(by): @Appender(_shared_docs['pivot'], indents=1) def pivot(data, index=None, columns=None, values=None): if values is None: - cols = [] # Make acceptable for multiple column indexes. + cols = [] if is_list_like(index): cols.extend(index) - else: - cols.append(index) + elif index is not None: + cols.extend([index]) cols.append(columns) + # if index is None: + # cols.append(columns) + # elif is_list_like(index): + # cols.extend(index) + # cols.append(columns) + # else: + # cols.extend([index]) + # cols.append(columns) + append = index is None indexed = data.set_index(cols, append=append) From caed2cd5e9e44c5ae496608820679f2f958d87d4 Mon Sep 17 00:00:00 2001 From: thoo Date: Sat, 16 Feb 2019 18:25:39 -0500 Subject: [PATCH 12/16] fix failing tests --- pandas/core/reshape/pivot.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/pandas/core/reshape/pivot.py b/pandas/core/reshape/pivot.py index 4fa07665c92f9..b28f41b07e70f 100644 --- a/pandas/core/reshape/pivot.py +++ b/pandas/core/reshape/pivot.py @@ -375,14 +375,6 @@ def pivot(data, index=None, columns=None, values=None): elif index is not None: cols.extend([index]) cols.append(columns) - # if index is None: - # cols.append(columns) - # elif is_list_like(index): - # cols.extend(index) - # cols.append(columns) - # else: - # cols.extend([index]) - # cols.append(columns) append = index is None indexed = data.set_index(cols, append=append) From 406b69064b34d4ff412fa729165c648d3dd726d0 Mon Sep 17 00:00:00 2001 From: thoo Date: Sun, 17 Feb 2019 13:00:56 -0500 Subject: [PATCH 13/16] Retrigger :pandas-devs failed From 2108301ba866708f63087f8e270e27bfcf2d032a Mon Sep 17 00:00:00 2001 From: thoo Date: Mon, 11 Mar 2019 13:38:59 -0400 Subject: [PATCH 14/16] Add example in reshaping.rst --- doc/source/user_guide/reshaping.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/doc/source/user_guide/reshaping.rst b/doc/source/user_guide/reshaping.rst index 5c11be34e6ed4..4406243aa8b5e 100644 --- a/doc/source/user_guide/reshaping.rst +++ b/doc/source/user_guide/reshaping.rst @@ -90,6 +90,19 @@ You can then select subsets from the pivoted ``DataFrame``: Note that this returns a view on the underlying data in the case where the data are homogeneously-typed. +Now :meth:`DataFrame.pivot` method also supports multiple columns as indexes. + +.. ipython:: python + + df1 = pd.DataFrame({'variable1': ['A', 'A', 'A', 'A', 'B', 'B', 'B', 'B'], + 'variable2': ['a', 'a', 'b', 'b', 'a', 'a', 'b', 'b'], + 'variable3': ['C', 'D', 'C', 'D', 'C', 'D', 'C', 'D'], + 'value': np.arange(8)}) + df1 + + df1.pivot(index=['variable1', 'variable2'], columns='variable3', + values='value') + .. note:: :func:`~pandas.pivot` will error with a ``ValueError: Index contains duplicate entries, cannot reshape`` if the index/column pair is not unique. In this From 1d0ce5d7986f4090316aa3d4c978a8506a963595 Mon Sep 17 00:00:00 2001 From: thoo Date: Mon, 11 Mar 2019 13:47:51 -0400 Subject: [PATCH 15/16] if-elif --- pandas/core/reshape/pivot.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pandas/core/reshape/pivot.py b/pandas/core/reshape/pivot.py index b28f41b07e70f..63449189b458b 100644 --- a/pandas/core/reshape/pivot.py +++ b/pandas/core/reshape/pivot.py @@ -369,11 +369,10 @@ def _convert_by(by): def pivot(data, index=None, columns=None, values=None): if values is None: # Make acceptable for multiple column indexes. - cols = [] - if is_list_like(index): - cols.extend(index) - elif index is not None: - cols.extend([index]) + if index is None: + cols = [columns] + elif is_list_like(index): + cols = index cols.append(columns) append = index is None From 0c25bba1fcfba2389c5848a338b58f677aa3c568 Mon Sep 17 00:00:00 2001 From: thoo Date: Mon, 11 Mar 2019 16:24:56 -0400 Subject: [PATCH 16/16] fix failing tests --- pandas/core/reshape/pivot.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/pandas/core/reshape/pivot.py b/pandas/core/reshape/pivot.py index 63449189b458b..843193a85ed7d 100644 --- a/pandas/core/reshape/pivot.py +++ b/pandas/core/reshape/pivot.py @@ -369,10 +369,13 @@ def _convert_by(by): def pivot(data, index=None, columns=None, values=None): if values is None: # Make acceptable for multiple column indexes. - if index is None: - cols = [columns] - elif is_list_like(index): - cols = index + # cols = [] + if is_list_like(index): + cols = index # cols.extend(index) + elif index is not None: + cols = [index] + else: + cols = [] cols.append(columns) append = index is None