331 lines
12 KiB
Python
331 lines
12 KiB
Python
import random
|
|
|
|
import numpy as np
|
|
import pytest
|
|
|
|
from pandas import DatetimeIndex, IntervalIndex, MultiIndex, Series
|
|
import pandas._testing as tm
|
|
|
|
|
|
class TestSeriesSortIndex:
|
|
def test_sort_index_name(self, datetime_series):
|
|
result = datetime_series.sort_index(ascending=False)
|
|
assert result.name == datetime_series.name
|
|
|
|
def test_sort_index(self, datetime_series):
|
|
datetime_series.index = datetime_series.index._with_freq(None)
|
|
|
|
rindex = list(datetime_series.index)
|
|
random.shuffle(rindex)
|
|
|
|
random_order = datetime_series.reindex(rindex)
|
|
sorted_series = random_order.sort_index()
|
|
tm.assert_series_equal(sorted_series, datetime_series)
|
|
|
|
# descending
|
|
sorted_series = random_order.sort_index(ascending=False)
|
|
tm.assert_series_equal(
|
|
sorted_series, datetime_series.reindex(datetime_series.index[::-1])
|
|
)
|
|
|
|
# compat on level
|
|
sorted_series = random_order.sort_index(level=0)
|
|
tm.assert_series_equal(sorted_series, datetime_series)
|
|
|
|
# compat on axis
|
|
sorted_series = random_order.sort_index(axis=0)
|
|
tm.assert_series_equal(sorted_series, datetime_series)
|
|
|
|
msg = "No axis named 1 for object type Series"
|
|
with pytest.raises(ValueError, match=msg):
|
|
random_order.sort_values(axis=1)
|
|
|
|
sorted_series = random_order.sort_index(level=0, axis=0)
|
|
tm.assert_series_equal(sorted_series, datetime_series)
|
|
|
|
with pytest.raises(ValueError, match=msg):
|
|
random_order.sort_index(level=0, axis=1)
|
|
|
|
def test_sort_index_inplace(self, datetime_series):
|
|
datetime_series.index = datetime_series.index._with_freq(None)
|
|
|
|
# For GH#11402
|
|
rindex = list(datetime_series.index)
|
|
random.shuffle(rindex)
|
|
|
|
# descending
|
|
random_order = datetime_series.reindex(rindex)
|
|
result = random_order.sort_index(ascending=False, inplace=True)
|
|
|
|
assert result is None
|
|
expected = datetime_series.reindex(datetime_series.index[::-1])
|
|
expected.index = expected.index._with_freq(None)
|
|
tm.assert_series_equal(random_order, expected)
|
|
|
|
# ascending
|
|
random_order = datetime_series.reindex(rindex)
|
|
result = random_order.sort_index(ascending=True, inplace=True)
|
|
|
|
assert result is None
|
|
expected = datetime_series.copy()
|
|
expected.index = expected.index._with_freq(None)
|
|
tm.assert_series_equal(random_order, expected)
|
|
|
|
def test_sort_index_level(self):
|
|
mi = MultiIndex.from_tuples([[1, 1, 3], [1, 1, 1]], names=list("ABC"))
|
|
s = Series([1, 2], mi)
|
|
backwards = s.iloc[[1, 0]]
|
|
|
|
res = s.sort_index(level="A")
|
|
tm.assert_series_equal(backwards, res)
|
|
|
|
res = s.sort_index(level=["A", "B"])
|
|
tm.assert_series_equal(backwards, res)
|
|
|
|
res = s.sort_index(level="A", sort_remaining=False)
|
|
tm.assert_series_equal(s, res)
|
|
|
|
res = s.sort_index(level=["A", "B"], sort_remaining=False)
|
|
tm.assert_series_equal(s, res)
|
|
|
|
@pytest.mark.parametrize("level", ["A", 0]) # GH#21052
|
|
def test_sort_index_multiindex(self, level):
|
|
|
|
mi = MultiIndex.from_tuples([[1, 1, 3], [1, 1, 1]], names=list("ABC"))
|
|
s = Series([1, 2], mi)
|
|
backwards = s.iloc[[1, 0]]
|
|
|
|
# implicit sort_remaining=True
|
|
res = s.sort_index(level=level)
|
|
tm.assert_series_equal(backwards, res)
|
|
|
|
# GH#13496
|
|
# sort has no effect without remaining lvls
|
|
res = s.sort_index(level=level, sort_remaining=False)
|
|
tm.assert_series_equal(s, res)
|
|
|
|
def test_sort_index_kind(self):
|
|
# GH#14444 & GH#13589: Add support for sort algo choosing
|
|
series = Series(index=[3, 2, 1, 4, 3], dtype=object)
|
|
expected_series = Series(index=[1, 2, 3, 3, 4], dtype=object)
|
|
|
|
index_sorted_series = series.sort_index(kind="mergesort")
|
|
tm.assert_series_equal(expected_series, index_sorted_series)
|
|
|
|
index_sorted_series = series.sort_index(kind="quicksort")
|
|
tm.assert_series_equal(expected_series, index_sorted_series)
|
|
|
|
index_sorted_series = series.sort_index(kind="heapsort")
|
|
tm.assert_series_equal(expected_series, index_sorted_series)
|
|
|
|
def test_sort_index_na_position(self):
|
|
series = Series(index=[3, 2, 1, 4, 3, np.nan], dtype=object)
|
|
expected_series_first = Series(index=[np.nan, 1, 2, 3, 3, 4], dtype=object)
|
|
|
|
index_sorted_series = series.sort_index(na_position="first")
|
|
tm.assert_series_equal(expected_series_first, index_sorted_series)
|
|
|
|
expected_series_last = Series(index=[1, 2, 3, 3, 4, np.nan], dtype=object)
|
|
|
|
index_sorted_series = series.sort_index(na_position="last")
|
|
tm.assert_series_equal(expected_series_last, index_sorted_series)
|
|
|
|
def test_sort_index_intervals(self):
|
|
s = Series(
|
|
[np.nan, 1, 2, 3], IntervalIndex.from_arrays([0, 1, 2, 3], [1, 2, 3, 4])
|
|
)
|
|
|
|
result = s.sort_index()
|
|
expected = s
|
|
tm.assert_series_equal(result, expected)
|
|
|
|
result = s.sort_index(ascending=False)
|
|
expected = Series(
|
|
[3, 2, 1, np.nan], IntervalIndex.from_arrays([3, 2, 1, 0], [4, 3, 2, 1])
|
|
)
|
|
tm.assert_series_equal(result, expected)
|
|
|
|
@pytest.mark.parametrize("inplace", [True, False])
|
|
@pytest.mark.parametrize(
|
|
"original_list, sorted_list, ascending, ignore_index, output_index",
|
|
[
|
|
([2, 3, 6, 1], [2, 3, 6, 1], True, True, [0, 1, 2, 3]),
|
|
([2, 3, 6, 1], [2, 3, 6, 1], True, False, [0, 1, 2, 3]),
|
|
([2, 3, 6, 1], [1, 6, 3, 2], False, True, [0, 1, 2, 3]),
|
|
([2, 3, 6, 1], [1, 6, 3, 2], False, False, [3, 2, 1, 0]),
|
|
],
|
|
)
|
|
def test_sort_index_ignore_index(
|
|
self, inplace, original_list, sorted_list, ascending, ignore_index, output_index
|
|
):
|
|
# GH 30114
|
|
ser = Series(original_list)
|
|
expected = Series(sorted_list, index=output_index)
|
|
kwargs = {
|
|
"ascending": ascending,
|
|
"ignore_index": ignore_index,
|
|
"inplace": inplace,
|
|
}
|
|
|
|
if inplace:
|
|
result_ser = ser.copy()
|
|
result_ser.sort_index(**kwargs)
|
|
else:
|
|
result_ser = ser.sort_index(**kwargs)
|
|
|
|
tm.assert_series_equal(result_ser, expected)
|
|
tm.assert_series_equal(ser, Series(original_list))
|
|
|
|
def test_sort_index_ascending_list(self):
|
|
# GH#16934
|
|
|
|
# Set up a Series with a three level MultiIndex
|
|
arrays = [
|
|
["bar", "bar", "baz", "baz", "foo", "foo", "qux", "qux"],
|
|
["one", "two", "one", "two", "one", "two", "one", "two"],
|
|
[4, 3, 2, 1, 4, 3, 2, 1],
|
|
]
|
|
tuples = zip(*arrays)
|
|
mi = MultiIndex.from_tuples(tuples, names=["first", "second", "third"])
|
|
ser = Series(range(8), index=mi)
|
|
|
|
# Sort with boolean ascending
|
|
result = ser.sort_index(level=["third", "first"], ascending=False)
|
|
expected = ser.iloc[[4, 0, 5, 1, 6, 2, 7, 3]]
|
|
tm.assert_series_equal(result, expected)
|
|
|
|
# Sort with list of boolean ascending
|
|
result = ser.sort_index(level=["third", "first"], ascending=[False, True])
|
|
expected = ser.iloc[[0, 4, 1, 5, 2, 6, 3, 7]]
|
|
tm.assert_series_equal(result, expected)
|
|
|
|
@pytest.mark.parametrize(
|
|
"ascending",
|
|
[
|
|
None,
|
|
(True, None),
|
|
(False, "True"),
|
|
],
|
|
)
|
|
def test_sort_index_ascending_bad_value_raises(self, ascending):
|
|
ser = Series(range(10), index=[0, 3, 2, 1, 4, 5, 7, 6, 8, 9])
|
|
match = 'For argument "ascending" expected type bool'
|
|
with pytest.raises(ValueError, match=match):
|
|
ser.sort_index(ascending=ascending)
|
|
|
|
|
|
class TestSeriesSortIndexKey:
|
|
def test_sort_index_multiindex_key(self):
|
|
mi = MultiIndex.from_tuples([[1, 1, 3], [1, 1, 1]], names=list("ABC"))
|
|
s = Series([1, 2], mi)
|
|
backwards = s.iloc[[1, 0]]
|
|
|
|
result = s.sort_index(level="C", key=lambda x: -x)
|
|
tm.assert_series_equal(s, result)
|
|
|
|
result = s.sort_index(level="C", key=lambda x: x) # nothing happens
|
|
tm.assert_series_equal(backwards, result)
|
|
|
|
def test_sort_index_multiindex_key_multi_level(self):
|
|
mi = MultiIndex.from_tuples([[1, 1, 3], [1, 1, 1]], names=list("ABC"))
|
|
s = Series([1, 2], mi)
|
|
backwards = s.iloc[[1, 0]]
|
|
|
|
result = s.sort_index(level=["A", "C"], key=lambda x: -x)
|
|
tm.assert_series_equal(s, result)
|
|
|
|
result = s.sort_index(level=["A", "C"], key=lambda x: x) # nothing happens
|
|
tm.assert_series_equal(backwards, result)
|
|
|
|
def test_sort_index_key(self):
|
|
series = Series(np.arange(6, dtype="int64"), index=list("aaBBca"))
|
|
|
|
result = series.sort_index()
|
|
expected = series.iloc[[2, 3, 0, 1, 5, 4]]
|
|
tm.assert_series_equal(result, expected)
|
|
|
|
result = series.sort_index(key=lambda x: x.str.lower())
|
|
expected = series.iloc[[0, 1, 5, 2, 3, 4]]
|
|
tm.assert_series_equal(result, expected)
|
|
|
|
result = series.sort_index(key=lambda x: x.str.lower(), ascending=False)
|
|
expected = series.iloc[[4, 2, 3, 0, 1, 5]]
|
|
tm.assert_series_equal(result, expected)
|
|
|
|
def test_sort_index_key_int(self):
|
|
series = Series(np.arange(6, dtype="int64"), index=np.arange(6, dtype="int64"))
|
|
|
|
result = series.sort_index()
|
|
tm.assert_series_equal(result, series)
|
|
|
|
result = series.sort_index(key=lambda x: -x)
|
|
expected = series.sort_index(ascending=False)
|
|
tm.assert_series_equal(result, expected)
|
|
|
|
result = series.sort_index(key=lambda x: 2 * x)
|
|
tm.assert_series_equal(result, series)
|
|
|
|
def test_sort_index_kind_key(self, sort_by_key):
|
|
# GH #14444 & #13589: Add support for sort algo choosing
|
|
series = Series(index=[3, 2, 1, 4, 3], dtype=object)
|
|
expected_series = Series(index=[1, 2, 3, 3, 4], dtype=object)
|
|
|
|
index_sorted_series = series.sort_index(kind="mergesort", key=sort_by_key)
|
|
tm.assert_series_equal(expected_series, index_sorted_series)
|
|
|
|
index_sorted_series = series.sort_index(kind="quicksort", key=sort_by_key)
|
|
tm.assert_series_equal(expected_series, index_sorted_series)
|
|
|
|
index_sorted_series = series.sort_index(kind="heapsort", key=sort_by_key)
|
|
tm.assert_series_equal(expected_series, index_sorted_series)
|
|
|
|
def test_sort_index_kind_neg_key(self):
|
|
# GH #14444 & #13589: Add support for sort algo choosing
|
|
series = Series(index=[3, 2, 1, 4, 3], dtype=object)
|
|
expected_series = Series(index=[4, 3, 3, 2, 1], dtype=object)
|
|
|
|
index_sorted_series = series.sort_index(kind="mergesort", key=lambda x: -x)
|
|
tm.assert_series_equal(expected_series, index_sorted_series)
|
|
|
|
index_sorted_series = series.sort_index(kind="quicksort", key=lambda x: -x)
|
|
tm.assert_series_equal(expected_series, index_sorted_series)
|
|
|
|
index_sorted_series = series.sort_index(kind="heapsort", key=lambda x: -x)
|
|
tm.assert_series_equal(expected_series, index_sorted_series)
|
|
|
|
def test_sort_index_na_position_key(self, sort_by_key):
|
|
series = Series(index=[3, 2, 1, 4, 3, np.nan], dtype=object)
|
|
expected_series_first = Series(index=[np.nan, 1, 2, 3, 3, 4], dtype=object)
|
|
|
|
index_sorted_series = series.sort_index(na_position="first", key=sort_by_key)
|
|
tm.assert_series_equal(expected_series_first, index_sorted_series)
|
|
|
|
expected_series_last = Series(index=[1, 2, 3, 3, 4, np.nan], dtype=object)
|
|
|
|
index_sorted_series = series.sort_index(na_position="last", key=sort_by_key)
|
|
tm.assert_series_equal(expected_series_last, index_sorted_series)
|
|
|
|
def test_changes_length_raises(self):
|
|
s = Series([1, 2, 3])
|
|
with pytest.raises(ValueError, match="change the shape"):
|
|
s.sort_index(key=lambda x: x[:1])
|
|
|
|
def test_sort_values_key_type(self):
|
|
s = Series([1, 2, 3], DatetimeIndex(["2008-10-24", "2008-11-23", "2007-12-22"]))
|
|
|
|
result = s.sort_index(key=lambda x: x.month)
|
|
expected = s.iloc[[0, 1, 2]]
|
|
tm.assert_series_equal(result, expected)
|
|
|
|
result = s.sort_index(key=lambda x: x.day)
|
|
expected = s.iloc[[2, 1, 0]]
|
|
tm.assert_series_equal(result, expected)
|
|
|
|
result = s.sort_index(key=lambda x: x.year)
|
|
expected = s.iloc[[2, 0, 1]]
|
|
tm.assert_series_equal(result, expected)
|
|
|
|
result = s.sort_index(key=lambda x: x.month_name())
|
|
expected = s.iloc[[2, 1, 0]]
|
|
tm.assert_series_equal(result, expected)
|