diff --git a/doc/source/api.rst b/doc/source/api.rst index f8068ebc38fa9..60f98cab96c4f 100644 --- a/doc/source/api.rst +++ b/doc/source/api.rst @@ -1166,6 +1166,8 @@ Attributes Index.values Index.is_monotonic + Index.is_monotonic_increasing + Index.is_monotonic_decreasing Index.is_unique Index.dtype Index.inferred_type diff --git a/doc/source/whatsnew/v0.15.1.txt b/doc/source/whatsnew/v0.15.1.txt index 343c6451d15ac..a371b5c830b2e 100644 --- a/doc/source/whatsnew/v0.15.1.txt +++ b/doc/source/whatsnew/v0.15.1.txt @@ -146,6 +146,29 @@ API changes s.dt.hour +- support for slicing with monotonic decreasing indexes, even if ``start`` or ``stop`` is + not found in the index (:issue:`7860`): + + .. ipython:: python + + s = pd.Series(['a', 'b', 'c', 'd'], [4, 3, 2, 1]) + s + + previous behavior: + + .. code-block:: python + + In [8]: s.loc[3.5:1.5] + KeyError: 3.5 + + current behavior: + + .. ipython:: python + + s.loc[3.5:1.5] + +- added Index properties `is_monotonic_increasing` and `is_monotonic_decreasing` (:issue:`8680`). + .. _whatsnew_0151.enhancements: Enhancements @@ -208,8 +231,9 @@ Bug Fixes - Bug in ix/loc block splitting on setitem (manifests with integer-like dtypes, e.g. datetime64) (:issue:`8607`) - - +- Bug when doing label based indexing with integers not found in the index for + non-unique but monotonic indexes (:issue:`8680`). +- Bug when indexing a Float64Index with ``np.nan`` on numpy 1.7 (:issue:`8980`). diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 71668a73d9286..bccc0e7b6be14 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -1461,7 +1461,7 @@ def xs(self, key, axis=0, level=None, copy=None, drop_level=True): name=self.index[loc]) else: - result = self[loc] + result = self.iloc[loc] result.index = new_index # this could be a view diff --git a/pandas/core/index.py b/pandas/core/index.py index 4f5a0c1f212c2..154410bbebf01 100644 --- a/pandas/core/index.py +++ b/pandas/core/index.py @@ -573,8 +573,22 @@ def _mpl_repr(self): @property def is_monotonic(self): - """ return if the index has monotonic (only equaly or increasing) values """ - return self._engine.is_monotonic + """ alias for is_monotonic_increasing (deprecated) """ + return self._engine.is_monotonic_increasing + + @property + def is_monotonic_increasing(self): + """ return if the index is monotonic increasing (only equal or + increasing) values + """ + return self._engine.is_monotonic_increasing + + @property + def is_monotonic_decreasing(self): + """ return if the index is monotonic decreasing (only equal or + decreasing values + """ + return self._engine.is_monotonic_decreasing def is_lexsorted_for_tuple(self, tup): return True @@ -1988,16 +2002,12 @@ def _get_slice(starting_value, offset, search_side, slice_property, slc += offset except KeyError: - if self.is_monotonic: - - # we are duplicated but non-unique - # so if we have an indexer then we are done - # else search for it (GH 7523) - if not is_unique and is_integer(search_value): - slc = search_value - else: - slc = self.searchsorted(search_value, - side=search_side) + if self.is_monotonic_increasing: + slc = self.searchsorted(search_value, side=search_side) + elif self.is_monotonic_decreasing: + search_side = 'right' if search_side == 'left' else 'left' + slc = len(self) - self[::-1].searchsorted(search_value, + side=search_side) else: raise return slc @@ -2431,10 +2441,13 @@ def __contains__(self, other): def get_loc(self, key): try: if np.all(np.isnan(key)): + nan_idxs = self._nan_idxs try: - return self._nan_idxs.item() - except ValueError: - return self._nan_idxs + return nan_idxs.item() + except (ValueError, IndexError): + # should only need to catch ValueError here but on numpy + # 1.7 .item() can raise IndexError when NaNs are present + return nan_idxs except (TypeError, NotImplementedError): pass return super(Float64Index, self).get_loc(key) diff --git a/pandas/index.pyx b/pandas/index.pyx index d6e358a96e904..73d886f10b241 100644 --- a/pandas/index.pyx +++ b/pandas/index.pyx @@ -77,7 +77,7 @@ cdef class IndexEngine: bint over_size_threshold cdef: - bint unique, monotonic + bint unique, monotonic_inc, monotonic_dec bint initialized, monotonic_check, unique_check def __init__(self, vgetter, n): @@ -89,7 +89,8 @@ cdef class IndexEngine: self.monotonic_check = 0 self.unique = 0 - self.monotonic = 0 + self.monotonic_inc = 0 + self.monotonic_dec = 0 def __contains__(self, object val): self._ensure_mapping_populated() @@ -134,7 +135,7 @@ cdef class IndexEngine: if is_definitely_invalid_key(val): raise TypeError - if self.over_size_threshold and self.is_monotonic: + if self.over_size_threshold and self.is_monotonic_increasing: if not self.is_unique: return self._get_loc_duplicates(val) values = self._get_index_values() @@ -158,7 +159,7 @@ cdef class IndexEngine: cdef: Py_ssize_t diff - if self.is_monotonic: + if self.is_monotonic_increasing: values = self._get_index_values() left = values.searchsorted(val, side='left') right = values.searchsorted(val, side='right') @@ -210,25 +211,35 @@ cdef class IndexEngine: return self.unique == 1 - property is_monotonic: + property is_monotonic_increasing: def __get__(self): if not self.monotonic_check: self._do_monotonic_check() - return self.monotonic == 1 + return self.monotonic_inc == 1 + + property is_monotonic_decreasing: + + def __get__(self): + if not self.monotonic_check: + self._do_monotonic_check() + + return self.monotonic_dec == 1 cdef inline _do_monotonic_check(self): try: values = self._get_index_values() - self.monotonic, unique = self._call_monotonic(values) + self.monotonic_inc, self.monotonic_dec, unique = \ + self._call_monotonic(values) if unique is not None: self.unique = unique self.unique_check = 1 except TypeError: - self.monotonic = 0 + self.monotonic_inc = 0 + self.monotonic_dec = 0 self.monotonic_check = 1 cdef _get_index_values(self): @@ -345,7 +356,7 @@ cdef class Int64Engine(IndexEngine): return _hash.Int64HashTable(n) def _call_monotonic(self, values): - return algos.is_monotonic_int64(values) + return algos.is_monotonic_int64(values, timelike=False) def get_pad_indexer(self, other, limit=None): return algos.pad_int64(self._get_index_values(), other, @@ -435,7 +446,7 @@ cdef class Float64Engine(IndexEngine): return result def _call_monotonic(self, values): - return algos.is_monotonic_float64(values) + return algos.is_monotonic_float64(values, timelike=False) def get_pad_indexer(self, other, limit=None): return algos.pad_float64(self._get_index_values(), other, @@ -489,7 +500,7 @@ cdef class ObjectEngine(IndexEngine): return _hash.PyObjectHashTable(n) def _call_monotonic(self, values): - return algos.is_monotonic_object(values) + return algos.is_monotonic_object(values, timelike=False) def get_pad_indexer(self, other, limit=None): return algos.pad_object(self._get_index_values(), other, @@ -506,7 +517,7 @@ cdef class DatetimeEngine(Int64Engine): return 'M8[ns]' def __contains__(self, object val): - if self.over_size_threshold and self.is_monotonic: + if self.over_size_threshold and self.is_monotonic_increasing: if not self.is_unique: return self._get_loc_duplicates(val) values = self._get_index_values() @@ -521,7 +532,7 @@ cdef class DatetimeEngine(Int64Engine): return self.vgetter().view('i8') def _call_monotonic(self, values): - return algos.is_monotonic_int64(values) + return algos.is_monotonic_int64(values, timelike=True) cpdef get_loc(self, object val): if is_definitely_invalid_key(val): @@ -529,7 +540,7 @@ cdef class DatetimeEngine(Int64Engine): # Welcome to the spaghetti factory - if self.over_size_threshold and self.is_monotonic: + if self.over_size_threshold and self.is_monotonic_increasing: if not self.is_unique: val = _to_i8(val) return self._get_loc_duplicates(val) diff --git a/pandas/src/generate_code.py b/pandas/src/generate_code.py index f7aede92d635d..d04f55bb19fff 100644 --- a/pandas/src/generate_code.py +++ b/pandas/src/generate_code.py @@ -539,31 +539,51 @@ def diff_2d_%(name)s(ndarray[%(c_type)s, ndim=2] arr, is_monotonic_template = """@cython.boundscheck(False) @cython.wraparound(False) -def is_monotonic_%(name)s(ndarray[%(c_type)s] arr): +def is_monotonic_%(name)s(ndarray[%(c_type)s] arr, bint timelike): ''' Returns ------- - is_monotonic, is_unique + is_monotonic_inc, is_monotonic_dec, is_unique ''' cdef: Py_ssize_t i, n %(c_type)s prev, cur bint is_unique = 1 + bint is_monotonic_inc = 1 + bint is_monotonic_dec = 1 n = len(arr) - if n < 2: - return True, True + if n == 1: + if arr[0] != arr[0] or (timelike and arr[0] == iNaT): + # single value is NaN + return False, False, True + else: + return True, True, True + elif n < 2: + return True, True, True + + if timelike and arr[0] == iNaT: + return False, False, None prev = arr[0] for i in range(1, n): cur = arr[i] + if timelike and cur == iNaT: + return False, False, None if cur < prev: - return False, None + is_monotonic_inc = 0 + elif cur > prev: + is_monotonic_dec = 0 elif cur == prev: is_unique = 0 + else: + # cur or prev is NaN + return False, False, None + if not is_monotonic_inc and not is_monotonic_dec: + return False, False, None prev = cur - return True, is_unique + return is_monotonic_inc, is_monotonic_dec, is_unique """ map_indices_template = """@cython.wraparound(False) diff --git a/pandas/src/generated.pyx b/pandas/src/generated.pyx index 50eefa5e783cf..01c80518ca21a 100644 --- a/pandas/src/generated.pyx +++ b/pandas/src/generated.pyx @@ -1799,166 +1799,286 @@ def backfill_2d_inplace_bool(ndarray[uint8_t, ndim=2] values, @cython.boundscheck(False) @cython.wraparound(False) -def is_monotonic_float64(ndarray[float64_t] arr): +def is_monotonic_float64(ndarray[float64_t] arr, bint timelike): ''' Returns ------- - is_monotonic, is_unique + is_monotonic_inc, is_monotonic_dec, is_unique ''' cdef: Py_ssize_t i, n float64_t prev, cur bint is_unique = 1 + bint is_monotonic_inc = 1 + bint is_monotonic_dec = 1 n = len(arr) - if n < 2: - return True, True + if n == 1: + if arr[0] != arr[0] or (timelike and arr[0] == iNaT): + # single value is NaN + return False, False, True + else: + return True, True, True + elif n < 2: + return True, True, True + + if timelike and arr[0] == iNaT: + return False, False, None prev = arr[0] for i in range(1, n): cur = arr[i] + if timelike and cur == iNaT: + return False, False, None if cur < prev: - return False, None + is_monotonic_inc = 0 + elif cur > prev: + is_monotonic_dec = 0 elif cur == prev: is_unique = 0 + else: + # cur or prev is NaN + return False, False, None + if not is_monotonic_inc and not is_monotonic_dec: + return False, False, None prev = cur - return True, is_unique + return is_monotonic_inc, is_monotonic_dec, is_unique @cython.boundscheck(False) @cython.wraparound(False) -def is_monotonic_float32(ndarray[float32_t] arr): +def is_monotonic_float32(ndarray[float32_t] arr, bint timelike): ''' Returns ------- - is_monotonic, is_unique + is_monotonic_inc, is_monotonic_dec, is_unique ''' cdef: Py_ssize_t i, n float32_t prev, cur bint is_unique = 1 + bint is_monotonic_inc = 1 + bint is_monotonic_dec = 1 n = len(arr) - if n < 2: - return True, True + if n == 1: + if arr[0] != arr[0] or (timelike and arr[0] == iNaT): + # single value is NaN + return False, False, True + else: + return True, True, True + elif n < 2: + return True, True, True + + if timelike and arr[0] == iNaT: + return False, False, None prev = arr[0] for i in range(1, n): cur = arr[i] + if timelike and cur == iNaT: + return False, False, None if cur < prev: - return False, None + is_monotonic_inc = 0 + elif cur > prev: + is_monotonic_dec = 0 elif cur == prev: is_unique = 0 + else: + # cur or prev is NaN + return False, False, None + if not is_monotonic_inc and not is_monotonic_dec: + return False, False, None prev = cur - return True, is_unique + return is_monotonic_inc, is_monotonic_dec, is_unique @cython.boundscheck(False) @cython.wraparound(False) -def is_monotonic_object(ndarray[object] arr): +def is_monotonic_object(ndarray[object] arr, bint timelike): ''' Returns ------- - is_monotonic, is_unique + is_monotonic_inc, is_monotonic_dec, is_unique ''' cdef: Py_ssize_t i, n object prev, cur bint is_unique = 1 + bint is_monotonic_inc = 1 + bint is_monotonic_dec = 1 n = len(arr) - if n < 2: - return True, True + if n == 1: + if arr[0] != arr[0] or (timelike and arr[0] == iNaT): + # single value is NaN + return False, False, True + else: + return True, True, True + elif n < 2: + return True, True, True + + if timelike and arr[0] == iNaT: + return False, False, None prev = arr[0] for i in range(1, n): cur = arr[i] + if timelike and cur == iNaT: + return False, False, None if cur < prev: - return False, None + is_monotonic_inc = 0 + elif cur > prev: + is_monotonic_dec = 0 elif cur == prev: is_unique = 0 + else: + # cur or prev is NaN + return False, False, None + if not is_monotonic_inc and not is_monotonic_dec: + return False, False, None prev = cur - return True, is_unique + return is_monotonic_inc, is_monotonic_dec, is_unique @cython.boundscheck(False) @cython.wraparound(False) -def is_monotonic_int32(ndarray[int32_t] arr): +def is_monotonic_int32(ndarray[int32_t] arr, bint timelike): ''' Returns ------- - is_monotonic, is_unique + is_monotonic_inc, is_monotonic_dec, is_unique ''' cdef: Py_ssize_t i, n int32_t prev, cur bint is_unique = 1 + bint is_monotonic_inc = 1 + bint is_monotonic_dec = 1 n = len(arr) - if n < 2: - return True, True + if n == 1: + if arr[0] != arr[0] or (timelike and arr[0] == iNaT): + # single value is NaN + return False, False, True + else: + return True, True, True + elif n < 2: + return True, True, True + + if timelike and arr[0] == iNaT: + return False, False, None prev = arr[0] for i in range(1, n): cur = arr[i] + if timelike and cur == iNaT: + return False, False, None if cur < prev: - return False, None + is_monotonic_inc = 0 + elif cur > prev: + is_monotonic_dec = 0 elif cur == prev: is_unique = 0 + else: + # cur or prev is NaN + return False, False, None + if not is_monotonic_inc and not is_monotonic_dec: + return False, False, None prev = cur - return True, is_unique + return is_monotonic_inc, is_monotonic_dec, is_unique @cython.boundscheck(False) @cython.wraparound(False) -def is_monotonic_int64(ndarray[int64_t] arr): +def is_monotonic_int64(ndarray[int64_t] arr, bint timelike): ''' Returns ------- - is_monotonic, is_unique + is_monotonic_inc, is_monotonic_dec, is_unique ''' cdef: Py_ssize_t i, n int64_t prev, cur bint is_unique = 1 + bint is_monotonic_inc = 1 + bint is_monotonic_dec = 1 n = len(arr) - if n < 2: - return True, True + if n == 1: + if arr[0] != arr[0] or (timelike and arr[0] == iNaT): + # single value is NaN + return False, False, True + else: + return True, True, True + elif n < 2: + return True, True, True + + if timelike and arr[0] == iNaT: + return False, False, None prev = arr[0] for i in range(1, n): cur = arr[i] + if timelike and cur == iNaT: + return False, False, None if cur < prev: - return False, None + is_monotonic_inc = 0 + elif cur > prev: + is_monotonic_dec = 0 elif cur == prev: is_unique = 0 + else: + # cur or prev is NaN + return False, False, None + if not is_monotonic_inc and not is_monotonic_dec: + return False, False, None prev = cur - return True, is_unique + return is_monotonic_inc, is_monotonic_dec, is_unique @cython.boundscheck(False) @cython.wraparound(False) -def is_monotonic_bool(ndarray[uint8_t] arr): +def is_monotonic_bool(ndarray[uint8_t] arr, bint timelike): ''' Returns ------- - is_monotonic, is_unique + is_monotonic_inc, is_monotonic_dec, is_unique ''' cdef: Py_ssize_t i, n uint8_t prev, cur bint is_unique = 1 + bint is_monotonic_inc = 1 + bint is_monotonic_dec = 1 n = len(arr) - if n < 2: - return True, True + if n == 1: + if arr[0] != arr[0] or (timelike and arr[0] == iNaT): + # single value is NaN + return False, False, True + else: + return True, True, True + elif n < 2: + return True, True, True + + if timelike and arr[0] == iNaT: + return False, False, None prev = arr[0] for i in range(1, n): cur = arr[i] + if timelike and cur == iNaT: + return False, False, None if cur < prev: - return False, None + is_monotonic_inc = 0 + elif cur > prev: + is_monotonic_dec = 0 elif cur == prev: is_unique = 0 + else: + # cur or prev is NaN + return False, False, None + if not is_monotonic_inc and not is_monotonic_dec: + return False, False, None prev = cur - return True, is_unique + return is_monotonic_inc, is_monotonic_dec, is_unique @cython.wraparound(False) @cython.boundscheck(False) diff --git a/pandas/tests/test_frame.py b/pandas/tests/test_frame.py index 1aa734c4834de..d46a219f3b1eb 100644 --- a/pandas/tests/test_frame.py +++ b/pandas/tests/test_frame.py @@ -866,7 +866,7 @@ def test_getitem_setitem_integer_slice_keyerrors(self): assert_frame_equal(result2, expected) # non-monotonic, raise KeyError - df2 = df[::-1] + df2 = df.iloc[lrange(5) + lrange(5, 10)[::-1]] self.assertRaises(KeyError, df2.ix.__getitem__, slice(3, 11)) self.assertRaises(KeyError, df2.ix.__setitem__, slice(3, 11), 0) diff --git a/pandas/tests/test_index.py b/pandas/tests/test_index.py index fe92cd55f1573..8ab5c30c49f10 100644 --- a/pandas/tests/test_index.py +++ b/pandas/tests/test_index.py @@ -848,33 +848,56 @@ def test_get_indexer(self): assert_almost_equal(r1, rbfill1) def test_slice_locs(self): - idx = Index([0, 1, 2, 5, 6, 7, 9, 10]) - n = len(idx) - - self.assertEqual(idx.slice_locs(start=2), (2, n)) - self.assertEqual(idx.slice_locs(start=3), (3, n)) - self.assertEqual(idx.slice_locs(3, 8), (3, 6)) - self.assertEqual(idx.slice_locs(5, 10), (3, n)) - self.assertEqual(idx.slice_locs(end=8), (0, 6)) - self.assertEqual(idx.slice_locs(end=9), (0, 7)) - - idx2 = idx[::-1] - self.assertRaises(KeyError, idx2.slice_locs, 8, 2) - self.assertRaises(KeyError, idx2.slice_locs, 7, 3) + for dtype in [int, float]: + idx = Index(np.array([0, 1, 2, 5, 6, 7, 9, 10], dtype=dtype)) + n = len(idx) + + self.assertEqual(idx.slice_locs(start=2), (2, n)) + self.assertEqual(idx.slice_locs(start=3), (3, n)) + self.assertEqual(idx.slice_locs(3, 8), (3, 6)) + self.assertEqual(idx.slice_locs(5, 10), (3, n)) + self.assertEqual(idx.slice_locs(5.0, 10.0), (3, n)) + self.assertEqual(idx.slice_locs(4.5, 10.5), (3, 8)) + self.assertEqual(idx.slice_locs(end=8), (0, 6)) + self.assertEqual(idx.slice_locs(end=9), (0, 7)) + + idx2 = idx[::-1] + self.assertEqual(idx2.slice_locs(8, 2), (2, 6)) + self.assertEqual(idx2.slice_locs(8.5, 1.5), (2, 6)) + self.assertEqual(idx2.slice_locs(7, 3), (2, 5)) + self.assertEqual(idx2.slice_locs(10.5, -1), (0, n)) def test_slice_locs_dup(self): idx = Index(['a', 'a', 'b', 'c', 'd', 'd']) - rs = idx.slice_locs('a', 'd') - self.assertEqual(rs, (0, 6)) - - rs = idx.slice_locs(end='d') - self.assertEqual(rs, (0, 6)) + self.assertEqual(idx.slice_locs('a', 'd'), (0, 6)) + self.assertEqual(idx.slice_locs(end='d'), (0, 6)) + self.assertEqual(idx.slice_locs('a', 'c'), (0, 4)) + self.assertEqual(idx.slice_locs('b', 'd'), (2, 6)) - rs = idx.slice_locs('a', 'c') - self.assertEqual(rs, (0, 4)) - - rs = idx.slice_locs('b', 'd') - self.assertEqual(rs, (2, 6)) + idx2 = idx[::-1] + self.assertEqual(idx2.slice_locs('d', 'a'), (0, 6)) + self.assertEqual(idx2.slice_locs(end='a'), (0, 6)) + self.assertEqual(idx2.slice_locs('d', 'b'), (0, 4)) + self.assertEqual(idx2.slice_locs('c', 'a'), (2, 6)) + + for dtype in [int, float]: + idx = Index(np.array([10, 12, 12, 14], dtype=dtype)) + self.assertEqual(idx.slice_locs(12, 12), (1, 3)) + self.assertEqual(idx.slice_locs(11, 13), (1, 3)) + + idx2 = idx[::-1] + self.assertEqual(idx2.slice_locs(12, 12), (1, 3)) + self.assertEqual(idx2.slice_locs(13, 11), (1, 3)) + + def test_slice_locs_na(self): + idx = Index([np.nan, 1, 2]) + self.assertRaises(KeyError, idx.slice_locs, start=1.5) + self.assertRaises(KeyError, idx.slice_locs, end=1.5) + self.assertEqual(idx.slice_locs(1), (1, 3)) + self.assertEqual(idx.slice_locs(np.nan), (0, 3)) + + idx = Index([np.nan, np.nan, 1, 2]) + self.assertRaises(KeyError, idx.slice_locs, np.nan) def test_drop(self): n = len(self.strIndex) @@ -922,6 +945,7 @@ def test_tuple_union_bug(self): def test_is_monotonic_incomparable(self): index = Index([5, datetime.now(), 7]) self.assertFalse(index.is_monotonic) + self.assertFalse(index.is_monotonic_decreasing) def test_get_set_value(self): values = np.random.randn(100) @@ -1286,6 +1310,15 @@ def test_equals(self): i2 = Float64Index([1.0,np.nan]) self.assertTrue(i.equals(i2)) + def test_get_loc_na(self): + idx = Float64Index([np.nan, 1, 2]) + self.assertEqual(idx.get_loc(1), 1) + self.assertEqual(idx.get_loc(np.nan), 0) + + idx = Float64Index([np.nan, 1, np.nan]) + self.assertEqual(idx.get_loc(1), 1) + self.assertRaises(KeyError, idx.slice_locs, np.nan) + def test_contains_nans(self): i = Float64Index([1.0, 2.0, np.nan]) self.assertTrue(np.nan in i) @@ -1403,9 +1436,31 @@ def test_dtype(self): def test_is_monotonic(self): self.assertTrue(self.index.is_monotonic) + self.assertTrue(self.index.is_monotonic_increasing) + self.assertFalse(self.index.is_monotonic_decreasing) index = Int64Index([4, 3, 2, 1]) self.assertFalse(index.is_monotonic) + self.assertTrue(index.is_monotonic_decreasing) + + index = Int64Index([1]) + self.assertTrue(index.is_monotonic) + self.assertTrue(index.is_monotonic_increasing) + self.assertTrue(index.is_monotonic_decreasing) + + def test_is_monotonic_na(self): + examples = [Index([np.nan]), + Index([np.nan, 1]), + Index([1, 2, np.nan]), + Index(['a', 'b', np.nan]), + pd.to_datetime(['NaT']), + pd.to_datetime(['NaT', '2000-01-01']), + pd.to_datetime(['2000-01-01', 'NaT', '2000-01-02']), + pd.to_timedelta(['1 day', 'NaT']), + ] + for index in examples: + self.assertFalse(index.is_monotonic_increasing) + self.assertFalse(index.is_monotonic_decreasing) def test_equals(self): same_values = Index(self.index, dtype=object) diff --git a/pandas/tests/test_series.py b/pandas/tests/test_series.py index 018d8c614eaae..938d171506461 100644 --- a/pandas/tests/test_series.py +++ b/pandas/tests/test_series.py @@ -1544,7 +1544,7 @@ def test_ix_getitem(self): def test_ix_getitem_not_monotonic(self): d1, d2 = self.ts.index[[5, 15]] - ts2 = self.ts[::2][::-1] + ts2 = self.ts[::2][[1, 2, 0]] self.assertRaises(KeyError, ts2.ix.__getitem__, slice(d1, d2)) self.assertRaises(KeyError, ts2.ix.__setitem__, slice(d1, d2), 0) @@ -1570,7 +1570,7 @@ def test_ix_getitem_setitem_integer_slice_keyerrors(self): assert_series_equal(result2, expected) # non-monotonic, raise KeyError - s2 = s[::-1] + s2 = s.iloc[lrange(5) + lrange(5, 10)[::-1]] self.assertRaises(KeyError, s2.ix.__getitem__, slice(3, 11)) self.assertRaises(KeyError, s2.ix.__setitem__, slice(3, 11), 0) diff --git a/pandas/tseries/tests/test_base.py b/pandas/tseries/tests/test_base.py index 367ea276646ee..917e10c4b7706 100644 --- a/pandas/tseries/tests/test_base.py +++ b/pandas/tseries/tests/test_base.py @@ -85,7 +85,7 @@ def test_asobject_tolist(self): def test_minmax(self): for tz in self.tz: # monotonic - idx1 = pd.DatetimeIndex([pd.NaT, '2011-01-01', '2011-01-02', + idx1 = pd.DatetimeIndex(['2011-01-01', '2011-01-02', '2011-01-03'], tz=tz) self.assertTrue(idx1.is_monotonic) @@ -305,7 +305,7 @@ def test_asobject_tolist(self): def test_minmax(self): # monotonic - idx1 = TimedeltaIndex(['nat', '1 days', '2 days', '3 days']) + idx1 = TimedeltaIndex(['1 days', '2 days', '3 days']) self.assertTrue(idx1.is_monotonic) # non-monotonic