Repository: pandas-dev/pandas

Issue:
API: add inplace to Series.sort/order
see #6848

Series.sort defaults to `inplace=True`
Series.order default to `inplace=False`

as they are inverses of each other



Discussion:

Resolving patch:
diff --git a/pandas/core/series.py b/pandas/core/series.py
--- 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):
         """


Test patch:
diff --git a/pandas/tests/test_indexing.py b/pandas/tests/test_indexing.py
--- 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
--- 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