ENH: indexing support for reversed is_monotonic · Issue #7860 · pandas-dev/pandas (original) (raw)

conceptually not hard (and you can look at a the slices to figure this out, e.g. if start >= end or start>last_endpoint, you can just do a reversed is_monotonic), to avoid a perf hit I think, then just reverse the searching operations for slices would need to do is_monotonic_decreasing here : https://github.com/pydata/pandas/blob/master/pandas/core/index.py#L1764

Hello,

I am working with spectral data, which for various spectral units such as
wavenumber, is often presented with decreasing spectral values along the
index. For example:

http://www.chemguide.co.uk/analysis/ir/irpropanone.GIF

In my dataframe, the index is stored in descending order (eg 500, 499,
498... 2, 1); however, when I try to slice using .ix[]; it becomes
impossible, giving me a long key error.

Likewise, df.plot() is sorting the xvalues from low to high, so I need to
reverse the plot axis after the fact. Not really a big deal, but wondered
if there's a better workaround.

Any suggestions?

Note: This behavior works fine for int64 index:

#Create dataframe and reverse index
x = DataFrame(np.random.randn(50,50))
x.index = x.index[::-1]

#Slice 30-10
x.ix[30:10, ::]

But fails for float index

x = DataFrame(np.random.randn(50,50), 
                  index=np.linspace(0,50))
x.index = x.index[::-1]

x.ix[30.0:10.0, ::]

With error:

 ---------------------------------------------------------------------------
 KeyError                                  Traceback (most recent call last)
 <ipython-input-68-1af3b9a79d3d> in <module>()
      11 x.index = x.index[::-1]
      12 
 ---> 13 x.ix[30.0:10.0, ::]
      14 

 /home/glue/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/pandas/core/indexing.pyc in __getitem__(self, key)
      67                 pass
      68 
 ---> 69             return self._getitem_tuple(key)
      70         else:
      71             return self._getitem_axis(key, axis=0)

 /home/glue/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/pandas/core/indexing.pyc in _getitem_tuple(self, tup)
     673                 continue
     674 
 --> 675             retval = getattr(retval, self.name)._getitem_axis(key, axis=i)
     676 
     677         return retval

 /home/glue/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/pandas/core/indexing.pyc in _getitem_axis(self, key, axis, validate_iterable)
     859         labels = self.obj._get_axis(axis)
     860         if isinstance(key, slice):
 --> 861             return self._get_slice_axis(key, axis=axis)
     862         elif _is_list_like(key) and not (isinstance(key, tuple) and
     863                                          isinstance(labels, MultiIndex)):

 /home/glue/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/pandas/core/indexing.pyc in _get_slice_axis(self, slice_obj, axis)
    1106         if not _need_slice(slice_obj):
    1107             return obj
 -> 1108         indexer = self._convert_slice_indexer(slice_obj, axis)
    1109 
    1110         if isinstance(indexer, slice):

 /home/glue/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/pandas/core/indexing.pyc in _convert_slice_indexer(self, key, axis)
     161         # if we are accessing via lowered dim, use the last dim
     162         ax = self.obj._get_axis(min(axis, self.ndim - 1))
 --> 163         return ax._convert_slice_indexer(key, typ=self.name)
     164 
     165     def _has_valid_setitem_indexer(self, indexer):

 /home/glue/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/pandas/core/index.pyc in _convert_slice_indexer(self, key, typ)
    2027 
    2028         # translate to locations
 -> 2029         return self.slice_indexer(key.start, key.stop, key.step)
    2030 
    2031     def get_value(self, series, key):

 /home/glue/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/pandas/core/index.pyc in slice_indexer(self, start, end, step)
    1704         This function assumes that the data is sorted, so use at your own peril
    1705         """
 -> 1706         start_slice, end_slice = self.slice_locs(start, end)
    1707 
    1708         # return a slice

 /home/glue/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/pandas/core/index.pyc in slice_locs(self, start, end)
    1777 
    1778         start_slice = _get_slice(0, offset=0, search_side='left',
 -> 1779                                  slice_property='start', search_value=start)
    1780         end_slice = _get_slice(len(self), offset=1, search_side='right',
    1781                                slice_property='stop', search_value=end)

 /home/glue/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/pandas/core/index.pyc in _get_slice(starting_value, offset, search_side, slice_property, search_value)
    1746 
    1747             try:
 -> 1748                 slc = self.get_loc(search_value)
    1749 
    1750                 if not is_unique:

 /home/glue/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/pandas/core/index.pyc in get_loc(self, key)
    2091         except (TypeError, NotImplementedError):
    2092             pass
 -> 2093         return super(Float64Index, self).get_loc(key)
    2094 
    2095     @property

 /home/glue/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/pandas/core/index.pyc in get_loc(self, key)
    1179         loc : int if unique index, possibly slice or mask if not
    1180         """
 -> 1181         return self._engine.get_loc(_values_from_object(key))
    1182 
    1183     def get_value(self, series, key):

 /home/glue/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/pandas/index.so in pandas.index.IndexEngine.get_loc (pandas/index.c:3354)()

 /home/glue/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/pandas/index.so in pandas.index.IndexEngine.get_loc (pandas/index.c:3234)()

 /home/glue/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/pandas/hashtable.so in pandas.hashtable.Float64HashTable.get_item (pandas/hashtable.c:9018)()

 /home/glue/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/pandas/hashtable.so in pandas.hashtable.Float64HashTable.get_item (pandas/hashtable.c:8962)()

 KeyError: 30.0