From 50c1e216bcc68a317b47e65ded8f9b7aa112f288 Mon Sep 17 00:00:00 2001 From: phofl Date: Wed, 14 Apr 2021 23:13:08 +0200 Subject: [PATCH] Add keyword sort to pivot_table --- doc/source/whatsnew/v1.3.0.rst | 1 + pandas/core/frame.py | 7 +++++++ pandas/core/reshape/pivot.py | 6 +++++- pandas/tests/reshape/test_pivot.py | 22 ++++++++++++++++++++++ 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index 38a1802340c69..afe6a3296f04d 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -219,6 +219,7 @@ Other enhancements - :meth:`pandas.read_csv` and :meth:`pandas.read_json` expose the argument ``encoding_errors`` to control how encoding errors are handled (:issue:`39450`) - :meth:`.GroupBy.any` and :meth:`.GroupBy.all` use Kleene logic with nullable data types (:issue:`37506`) - :meth:`.GroupBy.any` and :meth:`.GroupBy.all` return a ``BooleanDtype`` for columns with nullable data types (:issue:`33449`) +- Add keyword ``sort`` to :func:`pivot_table` to allow non-sorting of the result (:issue:`39143`) - .. --------------------------------------------------------------------------- diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 045776c3f5c50..7224a055fc148 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -7664,6 +7664,11 @@ def pivot(self, index=None, columns=None, values=None) -> DataFrame: .. versionchanged:: 0.25.0 + sort : bool, default True + Specifies if the result should be sorted. + + .. versionadded:: 1.3.0 + Returns ------- DataFrame @@ -7767,6 +7772,7 @@ def pivot_table( dropna=True, margins_name="All", observed=False, + sort=True, ) -> DataFrame: from pandas.core.reshape.pivot import pivot_table @@ -7781,6 +7787,7 @@ def pivot_table( dropna=dropna, margins_name=margins_name, observed=observed, + sort=sort, ) def stack(self, level: Level = -1, dropna: bool = True): diff --git a/pandas/core/reshape/pivot.py b/pandas/core/reshape/pivot.py index 795f5250012cb..e324534e0433f 100644 --- a/pandas/core/reshape/pivot.py +++ b/pandas/core/reshape/pivot.py @@ -64,6 +64,7 @@ def pivot_table( dropna=True, margins_name="All", observed=False, + sort=True, ) -> DataFrame: index = _convert_by(index) columns = _convert_by(columns) @@ -83,6 +84,7 @@ def pivot_table( dropna=dropna, margins_name=margins_name, observed=observed, + sort=sort, ) pieces.append(_table) keys.append(getattr(func, "__name__", func)) @@ -101,6 +103,7 @@ def pivot_table( dropna, margins_name, observed, + sort, ) return table.__finalize__(data, method="pivot_table") @@ -116,6 +119,7 @@ def __internal_pivot_table( dropna: bool, margins_name: str, observed: bool, + sort: bool, ) -> DataFrame: """ Helper of :func:`pandas.pivot_table` for any non-list ``aggfunc``. @@ -157,7 +161,7 @@ def __internal_pivot_table( pass values = list(values) - grouped = data.groupby(keys, observed=observed) + grouped = data.groupby(keys, observed=observed, sort=sort) agged = grouped.agg(aggfunc) if dropna and isinstance(agged, ABCDataFrame) and len(agged.columns): agged = agged.dropna(how="all") diff --git a/pandas/tests/reshape/test_pivot.py b/pandas/tests/reshape/test_pivot.py index 20aa0c9e2ee9a..3d1c3b81c492f 100644 --- a/pandas/tests/reshape/test_pivot.py +++ b/pandas/tests/reshape/test_pivot.py @@ -2115,6 +2115,28 @@ def test_pivot_table_doctest_case(self): expected = DataFrame(vals, columns=cols, index=index) tm.assert_frame_equal(table, expected) + def test_pivot_table_sort_false(self): + # GH#39143 + df = DataFrame( + { + "a": ["d1", "d4", "d3"], + "col": ["a", "b", "c"], + "num": [23, 21, 34], + "year": ["2018", "2018", "2019"], + } + ) + result = df.pivot_table( + index=["a", "col"], columns="year", values="num", aggfunc="sum", sort=False + ) + expected = DataFrame( + [[23, np.nan], [21, np.nan], [np.nan, 34]], + columns=Index(["2018", "2019"], name="year"), + index=MultiIndex.from_arrays( + [["d1", "d4", "d3"], ["a", "b", "c"]], names=["a", "col"] + ), + ) + tm.assert_frame_equal(result, expected) + class TestPivot: def test_pivot(self):