Skip to content

Commit

Permalink
DEPR: remove ix (pandas-dev#27620)
Browse files Browse the repository at this point in the history
  • Loading branch information
jbrockmendel authored and proost committed Dec 19, 2019
1 parent c6fcd08 commit 1f954cd
Show file tree
Hide file tree
Showing 16 changed files with 87 additions and 1,429 deletions.
14 changes: 6 additions & 8 deletions asv_bench/benchmarks/frame_methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,10 +321,9 @@ class Dropna:

def setup(self, how, axis):
self.df = DataFrame(np.random.randn(10000, 1000))
with warnings.catch_warnings(record=True):
self.df.ix[50:1000, 20:50] = np.nan
self.df.ix[2000:3000] = np.nan
self.df.ix[:, 60:70] = np.nan
self.df.iloc[50:1000, 20:50] = np.nan
self.df.iloc[2000:3000] = np.nan
self.df.iloc[:, 60:70] = np.nan
self.df_mixed = self.df.copy()
self.df_mixed["foo"] = "bar"

Expand All @@ -342,10 +341,9 @@ class Count:

def setup(self, axis):
self.df = DataFrame(np.random.randn(10000, 1000))
with warnings.catch_warnings(record=True):
self.df.ix[50:1000, 20:50] = np.nan
self.df.ix[2000:3000] = np.nan
self.df.ix[:, 60:70] = np.nan
self.df.iloc[50:1000, 20:50] = np.nan
self.df.iloc[2000:3000] = np.nan
self.df.iloc[:, 60:70] = np.nan
self.df_mixed = self.df.copy()
self.df_mixed["foo"] = "bar"

Expand Down
32 changes: 0 additions & 32 deletions asv_bench/benchmarks/indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,22 +67,6 @@ def time_iloc_scalar(self, index, index_structure):
def time_iloc_slice(self, index, index_structure):
self.data.iloc[:800000]

def time_ix_array(self, index, index_structure):
with warnings.catch_warnings(record=True):
self.data.ix[self.array]

def time_ix_list_like(self, index, index_structure):
with warnings.catch_warnings(record=True):
self.data.ix[[800000]]

def time_ix_scalar(self, index, index_structure):
with warnings.catch_warnings(record=True):
self.data.ix[800000]

def time_ix_slice(self, index, index_structure):
with warnings.catch_warnings(record=True):
self.data.ix[:800000]

def time_loc_array(self, index, index_structure):
self.data.loc[self.array]

Expand Down Expand Up @@ -148,10 +132,6 @@ def setup(self):
self.bool_indexer = self.df[self.col_scalar] > 0
self.bool_obj_indexer = self.bool_indexer.astype(object)

def time_ix(self):
with warnings.catch_warnings(record=True):
self.df.ix[self.idx_scalar, self.col_scalar]

def time_loc(self):
self.df.loc[self.idx_scalar, self.col_scalar]

Expand Down Expand Up @@ -228,14 +208,6 @@ def setup(self):
self.idx = IndexSlice[20000:30000, 20:30, 35:45, 30000:40000]
self.mdt = self.mdt.set_index(["A", "B", "C", "D"]).sort_index()

def time_series_ix(self):
with warnings.catch_warnings(record=True):
self.s.ix[999]

def time_frame_ix(self):
with warnings.catch_warnings(record=True):
self.df.ix[999]

def time_index_slice(self):
self.mdt.loc[self.idx, :]

Expand Down Expand Up @@ -310,10 +282,6 @@ def setup_cache(self):
def time_lookup_iloc(self, s):
s.iloc

def time_lookup_ix(self, s):
with warnings.catch_warnings(record=True):
s.ix

def time_lookup_loc(self, s):
s.loc

Expand Down
2 changes: 0 additions & 2 deletions doc/source/reference/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ public functions related to data types in pandas.
api/pandas.DataFrame.blocks
api/pandas.DataFrame.as_matrix
api/pandas.DataFrame.ix
api/pandas.Index.asi8
api/pandas.Index.data
api/pandas.Index.flags
Expand All @@ -60,7 +59,6 @@ public functions related to data types in pandas.
api/pandas.Series.asobject
api/pandas.Series.blocks
api/pandas.Series.from_array
api/pandas.Series.ix
api/pandas.Series.imag
api/pandas.Series.real

Expand Down
1 change: 1 addition & 0 deletions doc/source/whatsnew/v1.0.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,7 @@ or ``matplotlib.Axes.plot``. See :ref:`plotting.formatters` for more.
- :meth:`DataFrame.hist` and :meth:`Series.hist` no longer allows ``figsize="default"``, specify figure size by passinig a tuple instead (:issue:`30003`)
- Floordiv of integer-dtyped array by :class:`Timedelta` now raises ``TypeError`` (:issue:`21036`)
- :func:`pandas.api.types.infer_dtype` argument ``skipna`` defaults to ``True`` instead of ``False`` (:issue:`24050`)
- Removed the previously deprecated :attr:`Series.ix` and :attr:`DataFrame.ix` (:issue:`26438`)
- Removed the previously deprecated :meth:`Index.summary` (:issue:`18217`)
- Removed the previously deprecated "fastpath" keyword from the :class:`Index` constructor (:issue:`23110`)
- Removed the previously deprecated :meth:`Series.get_value`, :meth:`Series.set_value`, :meth:`DataFrame.get_value`, :meth:`DataFrame.set_value` (:issue:`17739`)
Expand Down
113 changes: 2 additions & 111 deletions pandas/core/indexing.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import textwrap
from typing import Tuple
import warnings

import numpy as np

Expand All @@ -10,10 +8,8 @@
from pandas.util._decorators import Appender

from pandas.core.dtypes.common import (
ensure_platform_int,
is_float,
is_integer,
is_integer_dtype,
is_iterator,
is_list_like,
is_numeric_dtype,
Expand All @@ -34,7 +30,6 @@
def get_indexers_list():

return [
("ix", _IXIndexer),
("iloc", _iLocIndexer),
("loc", _LocIndexer),
("at", _AtIndexer),
Expand Down Expand Up @@ -112,9 +107,7 @@ def __call__(self, axis=None):
new_self.axis = axis
return new_self

def __iter__(self):
raise NotImplementedError("ix is not iterable")

# TODO: remove once geopandas no longer needs this
def __getitem__(self, key):
# Used in ix and downstream in geopandas _CoordinateIndexer
if type(key) is tuple:
Expand Down Expand Up @@ -921,9 +914,6 @@ def _getitem_lowerdim(self, tup: Tuple):
if len(tup) > self.ndim:
raise IndexingError("Too many indexers. handle elsewhere")

# to avoid wasted computation
# df.ix[d1:d2, 0] -> columns first (True)
# df.ix[0, ['C', 'B', A']] -> rows first (False)
for i, key in enumerate(tup):
if is_label_like(key) or isinstance(key, tuple):
section = self._getitem_axis(key, axis=i)
Expand Down Expand Up @@ -1004,6 +994,7 @@ def _getitem_nested_tuple(self, tup: Tuple):

return obj

# TODO: remove once geopandas no longer needs __getitem__
def _getitem_axis(self, key, axis: int):
if is_iterator(key):
key = list(key)
Expand Down Expand Up @@ -1292,106 +1283,6 @@ def _get_slice_axis(self, slice_obj: slice, axis: int):
return self._slice(indexer, axis=axis, kind="iloc")


class _IXIndexer(_NDFrameIndexer):
"""
A primarily label-location based indexer, with integer position fallback.
Warning: Starting in 0.20.0, the .ix indexer is deprecated, in
favor of the more strict .iloc and .loc indexers.
``.ix[]`` supports mixed integer and label based access. It is
primarily label based, but will fall back to integer positional
access unless the corresponding axis is of integer type.
``.ix`` is the most general indexer and will support any of the
inputs in ``.loc`` and ``.iloc``. ``.ix`` also supports floating
point label schemes. ``.ix`` is exceptionally useful when dealing
with mixed positional and label based hierarchical indexes.
However, when an axis is integer based, ONLY label based access
and not positional access is supported. Thus, in such cases, it's
usually better to be explicit and use ``.iloc`` or ``.loc``.
See more at :ref:`Advanced Indexing <advanced>`.
"""

_ix_deprecation_warning = textwrap.dedent(
"""
.ix is deprecated. Please use
.loc for label based indexing or
.iloc for positional indexing
See the documentation here:
http://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#ix-indexer-is-deprecated""" # noqa: E501
)

def __init__(self, name, obj):
warnings.warn(self._ix_deprecation_warning, FutureWarning, stacklevel=2)
super().__init__(name, obj)

@Appender(_NDFrameIndexer._validate_key.__doc__)
def _validate_key(self, key, axis: int) -> bool:
"""
Returns
-------
bool
"""
if isinstance(key, slice):
return True

elif com.is_bool_indexer(key):
return True

elif is_list_like_indexer(key):
return True

else:

self._convert_scalar_indexer(key, axis)

return True

def _convert_for_reindex(self, key, axis: int):
"""
Transform a list of keys into a new array ready to be used as axis of
the object we return (e.g. including NaNs).
Parameters
----------
key : list-like
Targeted labels.
axis: int
Where the indexing is being made.
Returns
-------
list-like of labels.
"""
labels = self.obj._get_axis(axis)

if com.is_bool_indexer(key):
key = check_bool_indexer(labels, key)
return labels[key]

if isinstance(key, Index):
keyarr = labels._convert_index_indexer(key)
else:
# asarray can be unsafe, NumPy strings are weird
keyarr = com.asarray_tuplesafe(key)

if is_integer_dtype(keyarr):
# Cast the indexer to uint64 if possible so
# that the values returned from indexing are
# also uint64.
keyarr = labels._convert_arr_indexer(keyarr)

if not labels.is_integer():
keyarr = ensure_platform_int(keyarr)
return labels.take(keyarr)

return keyarr


class _LocationIndexer(_NDFrameIndexer):
def __getitem__(self, key):
if type(key) is tuple:
Expand Down
Loading

0 comments on commit 1f954cd

Please sign in to comment.