Skip to content

Commit 1f954cd

Browse files
jbrockmendelproost
authored andcommitted
DEPR: remove ix (pandas-dev#27620)
1 parent c6fcd08 commit 1f954cd

File tree

16 files changed

+87
-1429
lines changed

16 files changed

+87
-1429
lines changed

asv_bench/benchmarks/frame_methods.py

+6-8
Original file line numberDiff line numberDiff line change
@@ -321,10 +321,9 @@ class Dropna:
321321

322322
def setup(self, how, axis):
323323
self.df = DataFrame(np.random.randn(10000, 1000))
324-
with warnings.catch_warnings(record=True):
325-
self.df.ix[50:1000, 20:50] = np.nan
326-
self.df.ix[2000:3000] = np.nan
327-
self.df.ix[:, 60:70] = np.nan
324+
self.df.iloc[50:1000, 20:50] = np.nan
325+
self.df.iloc[2000:3000] = np.nan
326+
self.df.iloc[:, 60:70] = np.nan
328327
self.df_mixed = self.df.copy()
329328
self.df_mixed["foo"] = "bar"
330329

@@ -342,10 +341,9 @@ class Count:
342341

343342
def setup(self, axis):
344343
self.df = DataFrame(np.random.randn(10000, 1000))
345-
with warnings.catch_warnings(record=True):
346-
self.df.ix[50:1000, 20:50] = np.nan
347-
self.df.ix[2000:3000] = np.nan
348-
self.df.ix[:, 60:70] = np.nan
344+
self.df.iloc[50:1000, 20:50] = np.nan
345+
self.df.iloc[2000:3000] = np.nan
346+
self.df.iloc[:, 60:70] = np.nan
349347
self.df_mixed = self.df.copy()
350348
self.df_mixed["foo"] = "bar"
351349

asv_bench/benchmarks/indexing.py

-32
Original file line numberDiff line numberDiff line change
@@ -67,22 +67,6 @@ def time_iloc_scalar(self, index, index_structure):
6767
def time_iloc_slice(self, index, index_structure):
6868
self.data.iloc[:800000]
6969

70-
def time_ix_array(self, index, index_structure):
71-
with warnings.catch_warnings(record=True):
72-
self.data.ix[self.array]
73-
74-
def time_ix_list_like(self, index, index_structure):
75-
with warnings.catch_warnings(record=True):
76-
self.data.ix[[800000]]
77-
78-
def time_ix_scalar(self, index, index_structure):
79-
with warnings.catch_warnings(record=True):
80-
self.data.ix[800000]
81-
82-
def time_ix_slice(self, index, index_structure):
83-
with warnings.catch_warnings(record=True):
84-
self.data.ix[:800000]
85-
8670
def time_loc_array(self, index, index_structure):
8771
self.data.loc[self.array]
8872

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

151-
def time_ix(self):
152-
with warnings.catch_warnings(record=True):
153-
self.df.ix[self.idx_scalar, self.col_scalar]
154-
155135
def time_loc(self):
156136
self.df.loc[self.idx_scalar, self.col_scalar]
157137

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

231-
def time_series_ix(self):
232-
with warnings.catch_warnings(record=True):
233-
self.s.ix[999]
234-
235-
def time_frame_ix(self):
236-
with warnings.catch_warnings(record=True):
237-
self.df.ix[999]
238-
239211
def time_index_slice(self):
240212
self.mdt.loc[self.idx, :]
241213

@@ -310,10 +282,6 @@ def setup_cache(self):
310282
def time_lookup_iloc(self, s):
311283
s.iloc
312284

313-
def time_lookup_ix(self, s):
314-
with warnings.catch_warnings(record=True):
315-
s.ix
316-
317285
def time_lookup_loc(self, s):
318286
s.loc
319287

doc/source/reference/index.rst

-2
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ public functions related to data types in pandas.
4949
5050
api/pandas.DataFrame.blocks
5151
api/pandas.DataFrame.as_matrix
52-
api/pandas.DataFrame.ix
5352
api/pandas.Index.asi8
5453
api/pandas.Index.data
5554
api/pandas.Index.flags
@@ -60,7 +59,6 @@ public functions related to data types in pandas.
6059
api/pandas.Series.asobject
6160
api/pandas.Series.blocks
6261
api/pandas.Series.from_array
63-
api/pandas.Series.ix
6462
api/pandas.Series.imag
6563
api/pandas.Series.real
6664

doc/source/whatsnew/v1.0.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,7 @@ or ``matplotlib.Axes.plot``. See :ref:`plotting.formatters` for more.
535535
- :meth:`DataFrame.hist` and :meth:`Series.hist` no longer allows ``figsize="default"``, specify figure size by passinig a tuple instead (:issue:`30003`)
536536
- Floordiv of integer-dtyped array by :class:`Timedelta` now raises ``TypeError`` (:issue:`21036`)
537537
- :func:`pandas.api.types.infer_dtype` argument ``skipna`` defaults to ``True`` instead of ``False`` (:issue:`24050`)
538+
- Removed the previously deprecated :attr:`Series.ix` and :attr:`DataFrame.ix` (:issue:`26438`)
538539
- Removed the previously deprecated :meth:`Index.summary` (:issue:`18217`)
539540
- Removed the previously deprecated "fastpath" keyword from the :class:`Index` constructor (:issue:`23110`)
540541
- Removed the previously deprecated :meth:`Series.get_value`, :meth:`Series.set_value`, :meth:`DataFrame.get_value`, :meth:`DataFrame.set_value` (:issue:`17739`)

pandas/core/indexing.py

+2-111
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
import textwrap
21
from typing import Tuple
3-
import warnings
42

53
import numpy as np
64

@@ -10,10 +8,8 @@
108
from pandas.util._decorators import Appender
119

1210
from pandas.core.dtypes.common import (
13-
ensure_platform_int,
1411
is_float,
1512
is_integer,
16-
is_integer_dtype,
1713
is_iterator,
1814
is_list_like,
1915
is_numeric_dtype,
@@ -34,7 +30,6 @@
3430
def get_indexers_list():
3531

3632
return [
37-
("ix", _IXIndexer),
3833
("iloc", _iLocIndexer),
3934
("loc", _LocIndexer),
4035
("at", _AtIndexer),
@@ -112,9 +107,7 @@ def __call__(self, axis=None):
112107
new_self.axis = axis
113108
return new_self
114109

115-
def __iter__(self):
116-
raise NotImplementedError("ix is not iterable")
117-
110+
# TODO: remove once geopandas no longer needs this
118111
def __getitem__(self, key):
119112
# Used in ix and downstream in geopandas _CoordinateIndexer
120113
if type(key) is tuple:
@@ -921,9 +914,6 @@ def _getitem_lowerdim(self, tup: Tuple):
921914
if len(tup) > self.ndim:
922915
raise IndexingError("Too many indexers. handle elsewhere")
923916

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

1005995
return obj
1006996

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

12941285

1295-
class _IXIndexer(_NDFrameIndexer):
1296-
"""
1297-
A primarily label-location based indexer, with integer position fallback.
1298-
1299-
Warning: Starting in 0.20.0, the .ix indexer is deprecated, in
1300-
favor of the more strict .iloc and .loc indexers.
1301-
1302-
``.ix[]`` supports mixed integer and label based access. It is
1303-
primarily label based, but will fall back to integer positional
1304-
access unless the corresponding axis is of integer type.
1305-
1306-
``.ix`` is the most general indexer and will support any of the
1307-
inputs in ``.loc`` and ``.iloc``. ``.ix`` also supports floating
1308-
point label schemes. ``.ix`` is exceptionally useful when dealing
1309-
with mixed positional and label based hierarchical indexes.
1310-
1311-
However, when an axis is integer based, ONLY label based access
1312-
and not positional access is supported. Thus, in such cases, it's
1313-
usually better to be explicit and use ``.iloc`` or ``.loc``.
1314-
1315-
See more at :ref:`Advanced Indexing <advanced>`.
1316-
"""
1317-
1318-
_ix_deprecation_warning = textwrap.dedent(
1319-
"""
1320-
.ix is deprecated. Please use
1321-
.loc for label based indexing or
1322-
.iloc for positional indexing
1323-
1324-
See the documentation here:
1325-
http://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#ix-indexer-is-deprecated""" # noqa: E501
1326-
)
1327-
1328-
def __init__(self, name, obj):
1329-
warnings.warn(self._ix_deprecation_warning, FutureWarning, stacklevel=2)
1330-
super().__init__(name, obj)
1331-
1332-
@Appender(_NDFrameIndexer._validate_key.__doc__)
1333-
def _validate_key(self, key, axis: int) -> bool:
1334-
"""
1335-
Returns
1336-
-------
1337-
bool
1338-
"""
1339-
if isinstance(key, slice):
1340-
return True
1341-
1342-
elif com.is_bool_indexer(key):
1343-
return True
1344-
1345-
elif is_list_like_indexer(key):
1346-
return True
1347-
1348-
else:
1349-
1350-
self._convert_scalar_indexer(key, axis)
1351-
1352-
return True
1353-
1354-
def _convert_for_reindex(self, key, axis: int):
1355-
"""
1356-
Transform a list of keys into a new array ready to be used as axis of
1357-
the object we return (e.g. including NaNs).
1358-
1359-
Parameters
1360-
----------
1361-
key : list-like
1362-
Targeted labels.
1363-
axis: int
1364-
Where the indexing is being made.
1365-
1366-
Returns
1367-
-------
1368-
list-like of labels.
1369-
"""
1370-
labels = self.obj._get_axis(axis)
1371-
1372-
if com.is_bool_indexer(key):
1373-
key = check_bool_indexer(labels, key)
1374-
return labels[key]
1375-
1376-
if isinstance(key, Index):
1377-
keyarr = labels._convert_index_indexer(key)
1378-
else:
1379-
# asarray can be unsafe, NumPy strings are weird
1380-
keyarr = com.asarray_tuplesafe(key)
1381-
1382-
if is_integer_dtype(keyarr):
1383-
# Cast the indexer to uint64 if possible so
1384-
# that the values returned from indexing are
1385-
# also uint64.
1386-
keyarr = labels._convert_arr_indexer(keyarr)
1387-
1388-
if not labels.is_integer():
1389-
keyarr = ensure_platform_int(keyarr)
1390-
return labels.take(keyarr)
1391-
1392-
return keyarr
1393-
1394-
13951286
class _LocationIndexer(_NDFrameIndexer):
13961287
def __getitem__(self, key):
13971288
if type(key) is tuple:

0 commit comments

Comments
 (0)