-
-
Notifications
You must be signed in to change notification settings - Fork 18.4k
DEPR: remove ix #27620
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DEPR: remove ix #27620
Changes from 15 commits
704b422
ec02d1f
db1567f
c8ff4a0
2c8ef9a
1ed8a96
8abdbaf
23d2eca
ecc8b36
9f78ec7
3ca8c86
812b5fb
2e09bd6
966f749
18033b4
b9f61cb
c319080
e467976
cb7ef3b
52f4ff1
ffd50b0
0f271c1
44eb4fc
bf9f3b3
36afdbe
fcc9db7
79b441c
223382b
1756a69
07b393b
f9a394a
3d484cd
247eabf
7dc7de6
2b3dba7
721d88b
0ca6762
446c21f
a2aef80
74127d6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,10 +10,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, | ||
|
@@ -34,7 +32,6 @@ | |
def get_indexers_list(): | ||
|
||
return [ | ||
("ix", _IXIndexer), | ||
("iloc", _iLocIndexer), | ||
("loc", _LocIndexer), | ||
("at", _AtIndexer), | ||
|
@@ -113,9 +110,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: | ||
|
@@ -148,6 +143,42 @@ def __getitem__(self, key): | |
key = com.apply_if_callable(key, self.obj) | ||
return self._getitem_axis(key, axis=axis) | ||
|
||
# TODO: remove once geopandas no longer needs __getitem__ | ||
def _getitem_axis(self, key, axis: int): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was simply moved from location below right? Not a big deal just want to make sure there isn't something with the diff I am overlooking There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i think this got moved in a rebase mixup, yah |
||
if is_iterator(key): | ||
key = list(key) | ||
self._validate_key(key, axis) | ||
|
||
labels = self.obj._get_axis(axis) | ||
if isinstance(key, slice): | ||
return self._get_slice_axis(key, axis=axis) | ||
elif is_list_like_indexer(key) and not ( | ||
isinstance(key, tuple) and isinstance(labels, MultiIndex) | ||
): | ||
|
||
if hasattr(key, "ndim") and key.ndim > 1: | ||
raise ValueError("Cannot index with multidimensional key") | ||
|
||
return self._getitem_iterable(key, axis=axis) | ||
else: | ||
|
||
# maybe coerce a float scalar to integer | ||
key = labels._maybe_cast_indexer(key) | ||
|
||
if is_integer(key): | ||
if axis == 0 and isinstance(labels, MultiIndex): | ||
try: | ||
return self._get_label(key, axis=axis) | ||
except (KeyError, TypeError): | ||
if self.obj.index.levels[0].is_integer(): | ||
raise | ||
|
||
# this is the fallback! (for a non-float, non-integer index) | ||
if not labels.is_floating() and not labels.is_integer(): | ||
return self._get_loc(key, axis=axis) | ||
|
||
return self._get_label(key, axis=axis) | ||
|
||
def _get_label(self, label, axis: int): | ||
if self.ndim == 1: | ||
# for perf reasons we want to try _xs first | ||
|
@@ -912,9 +943,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) | ||
|
@@ -995,41 +1023,6 @@ def _getitem_nested_tuple(self, tup: Tuple): | |
|
||
return obj | ||
|
||
def _getitem_axis(self, key, axis: int): | ||
if is_iterator(key): | ||
key = list(key) | ||
self._validate_key(key, axis) | ||
|
||
labels = self.obj._get_axis(axis) | ||
if isinstance(key, slice): | ||
return self._get_slice_axis(key, axis=axis) | ||
elif is_list_like_indexer(key) and not ( | ||
isinstance(key, tuple) and isinstance(labels, MultiIndex) | ||
): | ||
|
||
if hasattr(key, "ndim") and key.ndim > 1: | ||
raise ValueError("Cannot index with multidimensional key") | ||
|
||
return self._getitem_iterable(key, axis=axis) | ||
else: | ||
|
||
# maybe coerce a float scalar to integer | ||
key = labels._maybe_cast_indexer(key) | ||
|
||
if is_integer(key): | ||
if axis == 0 and isinstance(labels, MultiIndex): | ||
try: | ||
return self._get_label(key, axis=axis) | ||
except (KeyError, TypeError): | ||
if self.obj.index.levels[0].is_integer(): | ||
raise | ||
|
||
# this is the fallback! (for a non-float, non-integer index) | ||
if not labels.is_floating() and not labels.is_integer(): | ||
return self._get_loc(key, axis=axis) | ||
|
||
return self._get_label(key, axis=axis) | ||
|
||
def _get_listlike_indexer(self, key, axis: int, raise_missing: bool = False): | ||
""" | ||
Transform a list-like of keys into a new index and an indexer. | ||
|
@@ -1286,102 +1279,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): | ||
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 | ||
Target 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): | ||
_exception = Exception | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we keep this method? (or part of it, for compat with released geopandas)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense. Possibly with a warning telling users they need to upgrade geopandas?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, that sounds good. But maybe start having it as a DeprecationWarning? Then we can easily switch to FutureWarning once there is an actual geopandas release.