From 15c3b9f2a3a11a3b359afe02e0ba98a832f9d721 Mon Sep 17 00:00:00 2001 From: jreback Date: Thu, 10 Apr 2014 09:53:51 -0400 Subject: [PATCH] API: add inplace keyword to Series.order/sort to make them inverses (GH6859) --- doc/source/release.rst | 1 + doc/source/v0.14.0.txt | 1 + pandas/core/series.py | 83 +++++++++++++++++++---------------- pandas/tests/test_indexing.py | 8 ---- pandas/tests/test_series.py | 24 +++++++++- 5 files changed, 71 insertions(+), 46 deletions(-) diff --git a/doc/source/release.rst b/doc/source/release.rst index 2ac6d96c5a36b..df547c3f0a09b 100644 --- a/doc/source/release.rst +++ b/doc/source/release.rst @@ -170,6 +170,7 @@ API Changes add ``na_position`` arg to conform to ``Series.order`` (:issue:`6847`) - default sorting algorithm for ``Series.order`` is not ``quicksort``, to conform with ``Series.sort`` (and numpy defaults) +- add ``inplace`` keyword to ``Series.order/sort`` to make them inverses (:issue:`6859`) Deprecations ~~~~~~~~~~~~ diff --git a/doc/source/v0.14.0.txt b/doc/source/v0.14.0.txt index 05569dbdba702..d4f912baaa4dc 100644 --- a/doc/source/v0.14.0.txt +++ b/doc/source/v0.14.0.txt @@ -212,6 +212,7 @@ API changes add ``na_position`` arg to conform to ``Series.order`` (:issue:`6847`) - default sorting algorithm for ``Series.order`` is not ``quicksort``, to conform with ``Series.sort`` (and numpy defaults) +- add ``inplace`` keyword to ``Series.order/sort`` to make them inverses (:issue:`6859`) .. _whatsnew_0140.sql: diff --git a/pandas/core/series.py b/pandas/core/series.py index 3b1c7a6af5069..c4901e78779b1 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -1563,39 +1563,6 @@ def update(self, other): #---------------------------------------------------------------------- # Reindexing, sorting - def sort(self, axis=0, ascending=True, kind='quicksort', na_position='last'): - """ - Sort values and index labels by value, in place. For compatibility with - ndarray API. No return value - - Parameters - ---------- - axis : int (can only be zero) - ascending : boolean, default True - Sort ascending. Passing False sorts descending - kind : {'mergesort', 'quicksort', 'heapsort'}, default 'quicksort' - Choice of sorting algorithm. See np.sort for more - information. 'mergesort' is the only stable algorithm - na_position : {'first', 'last'} (optional, default='last') - 'first' puts NaNs at the beginning - 'last' puts NaNs at the end - - See Also - -------- - Series.order - """ - - # GH 5856/5863 - if self._is_cached: - raise ValueError("This Series is a view of some other array, to " - "sort in-place you must create a copy") - - result = self.order(ascending=ascending, - kind=kind, - na_position=na_position) - - self._update_inplace(result) - def sort_index(self, ascending=True): """ Sort object by labels (along an axis) @@ -1692,9 +1659,38 @@ def rank(self, method='average', na_option='keep', ascending=True, ascending=ascending, pct=pct) return self._constructor(ranks, index=self.index).__finalize__(self) - def order(self, na_last=None, ascending=True, kind='quicksort', na_position='last'): + def sort(self, axis=0, ascending=True, kind='quicksort', na_position='last', inplace=True): """ - Sorts Series object, by value, maintaining index-value link + Sort values and index labels by value. This is an inplace sort by default. + Series.order is the equivalent but returns a new Series. + + Parameters + ---------- + axis : int (can only be zero) + ascending : boolean, default True + Sort ascending. Passing False sorts descending + kind : {'mergesort', 'quicksort', 'heapsort'}, default 'quicksort' + Choice of sorting algorithm. See np.sort for more + information. 'mergesort' is the only stable algorithm + na_position : {'first', 'last'} (optional, default='last') + 'first' puts NaNs at the beginning + 'last' puts NaNs at the end + inplace : boolean, default True + Do operation in place. + + See Also + -------- + Series.order + """ + return self.order(ascending=ascending, + kind=kind, + na_position=na_position, + inplace=inplace) + + def order(self, na_last=None, ascending=True, kind='quicksort', na_position='last', inplace=False): + """ + Sorts Series object, by value, maintaining index-value link. + This will return a new Series by default. Series.sort is the equivalent but as an inplace method. Parameters ---------- @@ -1708,6 +1704,8 @@ def order(self, na_last=None, ascending=True, kind='quicksort', na_position='las na_position : {'first', 'last'} (optional, default='last') 'first' puts NaNs at the beginning 'last' puts NaNs at the end + inplace : boolean, default False + Do operation in place. Returns ------- @@ -1717,6 +1715,12 @@ def order(self, na_last=None, ascending=True, kind='quicksort', na_position='las -------- Series.sort """ + + # GH 5856/5853 + if inplace and self._is_cached: + raise ValueError("This Series is a view of some other array, to " + "sort in-place you must create a copy") + if na_last is not None: warnings.warn(("na_last is deprecated. Please use na_position instead"), FutureWarning) @@ -1755,8 +1759,13 @@ def _try_kind_sort(arr): sortedIdx[:n] = idx[bad] else: raise ValueError('invalid na_position: {!r}'.format(na_position)) - return self._constructor(arr[sortedIdx], index=self.index[sortedIdx])\ - .__finalize__(self) + + result = self._constructor(arr[sortedIdx], index=self.index[sortedIdx]) + + if inplace: + self._update_inplace(result) + else: + return result.__finalize__(self) def sortlevel(self, level=0, ascending=True): """ diff --git a/pandas/tests/test_indexing.py b/pandas/tests/test_indexing.py index ea1e07dbf6acc..277523855da67 100644 --- a/pandas/tests/test_indexing.py +++ b/pandas/tests/test_indexing.py @@ -2848,14 +2848,6 @@ def f(): zed['eyes']['right'].fillna(value=555, inplace=True) self.assertRaises(com.SettingWithCopyError, f) - # GH 5856/5863 - # Series.sort operating on a view - df = DataFrame(np.random.randn(10,4)) - s = df.iloc[:,0] - def f(): - s.sort() - self.assertRaises(ValueError, f) - df = DataFrame(np.random.randn(10,4)) s = df.iloc[:,0] s = s.order() diff --git a/pandas/tests/test_series.py b/pandas/tests/test_series.py index 73dd47ee3d3e4..f4a8d4eed2c41 100644 --- a/pandas/tests/test_series.py +++ b/pandas/tests/test_series.py @@ -3825,7 +3825,7 @@ def test_dot(self): self.assertRaises(ValueError, a.dot, b.T) def test_value_counts_nunique(self): - + # basics.rst doc example series = Series(np.random.randn(500)) series[20:500] = np.nan @@ -3911,6 +3911,28 @@ def test_sort(self): self.assert_numpy_array_equal(ts.index, self.ts.order(ascending=False).index) + # GH 5856/5853 + # Series.sort operating on a view + df = DataFrame(np.random.randn(10,4)) + s = df.iloc[:,0] + def f(): + s.sort() + self.assertRaises(ValueError, f) + + # test order/sort inplace + # GH6859 + ts1 = self.ts.copy() + ts1.sort(ascending=False) + ts2 = self.ts.copy() + ts2.order(ascending=False,inplace=True) + assert_series_equal(ts1,ts2) + + ts1 = self.ts.copy() + ts1 = ts1.sort(ascending=False,inplace=False) + ts2 = self.ts.copy() + ts2 = ts.order(ascending=False) + assert_series_equal(ts1,ts2) + def test_sort_index(self): import random