diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 4e05dfca43e78..0e2253aed1c88 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -274,7 +274,6 @@ def _setup_axes( info_axis=None, stat_axis=None, aliases=None, - slicers=None, axes_are_reversed=False, build_axes=True, ns=None, @@ -288,7 +287,6 @@ def _setup_axes( info_axis_num : the axis of the selector dimension (int) stat_axis_num : the number of axis for the default stats (int) aliases : other names for a single axis (dict) - slicers : how axes slice to others (dict) axes_are_reversed : boolean whether to treat passed axes as reversed (DataFrame) build_axes : setup the axis properties (default True) @@ -300,7 +298,6 @@ def _setup_axes( cls._AXIS_ALIASES = aliases or dict() cls._AXIS_IALIASES = {v: k for k, v in cls._AXIS_ALIASES.items()} cls._AXIS_NAMES = dict(enumerate(axes)) - cls._AXIS_SLICEMAP = slicers or None cls._AXIS_REVERSED = axes_are_reversed # typ @@ -347,15 +344,6 @@ def _construct_axes_dict_from(self, axes, **kwargs): d.update(kwargs) return d - def _construct_axes_dict_for_slice(self, axes=None, **kwargs): - """Return an axes dictionary for myself.""" - d = { - self._AXIS_SLICEMAP[a]: self._get_axis(a) - for a in (axes or self._AXIS_ORDERS) - } - d.update(kwargs) - return d - def _construct_axes_from_arguments( self, args, kwargs, require_all=False, sentinel=None ): @@ -577,18 +565,6 @@ def _obj_with_exclusions(self): """ internal compat with SelectionMixin """ return self - def _expand_axes(self, key): - new_axes = [] - for k, ax in zip(key, self.axes): - if k not in ax: - if type(k) != ax.dtype.type: - ax = ax.astype("O") - new_axes.append(ax.insert(len(ax), k)) - else: - new_axes.append(ax) - - return new_axes - def set_axis(self, labels, axis=0, inplace=None): """ Assign desired index to given axis. diff --git a/pandas/core/indexers.py b/pandas/core/indexers.py index 7b0030b91e4dc..70c48e969172f 100644 --- a/pandas/core/indexers.py +++ b/pandas/core/indexers.py @@ -36,9 +36,19 @@ def is_scalar_indexer(indexer, arr_value) -> bool: return False -def is_empty_indexer(indexer, arr_value) -> bool: - # return a boolean if we have an empty indexer +def is_empty_indexer(indexer, arr_value: np.ndarray) -> bool: + """ + Check if we have an empty indexer. + + Parameters + ---------- + indexer : object + arr_value : np.ndarray + Returns + ------- + bool + """ if is_list_like(indexer) and not len(indexer): return True if arr_value.ndim == 1: diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py index c31d6538ad2c3..01f338a021cec 100755 --- a/pandas/core/indexing.py +++ b/pandas/core/indexing.py @@ -158,9 +158,7 @@ def _get_label(self, label, axis=None): return self.obj._xs(label, axis=axis) - def _get_loc(self, key, axis=None): - if axis is None: - axis = self.axis + def _get_loc(self, key, axis: int): return self.obj._ixs(key, axis=axis) def _slice(self, obj, axis=None, kind=None): @@ -172,11 +170,11 @@ def _get_setitem_indexer(self, key): if self.axis is not None: return self._convert_tuple(key, is_setter=True) - axis = self.obj._get_axis(0) + ax = self.obj._get_axis(0) - if isinstance(axis, MultiIndex) and self.name != "iloc": + if isinstance(ax, MultiIndex) and self.name != "iloc": try: - return axis.get_loc(key) + return ax.get_loc(key) except Exception: pass @@ -189,8 +187,9 @@ def _get_setitem_indexer(self, key): if isinstance(key, range): return self._convert_range(key, is_setter=True) + axis = self.axis or 0 try: - return self._convert_to_indexer(key, is_setter=True) + return self._convert_to_indexer(key, axis=axis, is_setter=True) except TypeError as e: # invalid indexer type vs 'other' indexing errors @@ -206,7 +205,7 @@ def __setitem__(self, key, value): indexer = self._get_setitem_indexer(key) self._setitem_with_indexer(indexer, value) - def _validate_key(self, key, axis): + def _validate_key(self, key, axis: int): """ Ensure that key is valid for current indexer. @@ -214,7 +213,6 @@ def _validate_key(self, key, axis): ---------- key : scalar, slice or list-like The key requested - axis : int Dimension on which the indexing is being made @@ -222,14 +220,12 @@ def _validate_key(self, key, axis): ------ TypeError If the key (or some element of it) has wrong type - IndexError If the key (or some element of it) is out of bounds - KeyError If the key was not found """ - raise AbstractMethodError() + raise AbstractMethodError(self) def _has_valid_tuple(self, key): """ check the key for valid keys across my indexer """ @@ -249,7 +245,7 @@ def _is_nested_tuple_indexer(self, tup): return any(is_nested_tuple(tup, ax) for ax in self.obj.axes) return False - def _convert_tuple(self, key, is_setter=False): + def _convert_tuple(self, key, is_setter: bool = False): keyidx = [] if self.axis is not None: axis = self.obj._get_axis_number(self.axis) @@ -268,19 +264,17 @@ def _convert_tuple(self, key, is_setter=False): keyidx.append(idx) return tuple(keyidx) - def _convert_range(self, key, is_setter=False): + def _convert_range(self, key, is_setter: bool = False): """ convert a range argument """ return list(key) - def _convert_scalar_indexer(self, key, axis): + def _convert_scalar_indexer(self, key, axis: int): # if we are accessing via lowered dim, use the last dim - if axis is None: - axis = 0 ax = self.obj._get_axis(min(axis, self.ndim - 1)) # a scalar return ax._convert_scalar_indexer(key, kind=self.name) - def _convert_slice_indexer(self, key, axis): + def _convert_slice_indexer(self, key, axis: int): # if we are accessing via lowered dim, use the last dim ax = self.obj._get_axis(min(axis, self.ndim - 1)) return ax._convert_slice_indexer(key, kind=self.name) @@ -883,7 +877,7 @@ def _multi_take(self, tup): } return o._reindex_with_indexers(d, copy=True, allow_dups=True) - def _convert_for_reindex(self, key, axis=None): + def _convert_for_reindex(self, key, axis: int): return key def _handle_lowerdim_multi_index_axis0(self, tup): @@ -1055,7 +1049,7 @@ def _getitem_axis(self, key, axis=None): return self._get_label(key, axis=axis) - def _get_listlike_indexer(self, key, axis, raise_missing=False): + 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. @@ -1151,7 +1145,9 @@ def _getitem_iterable(self, key, axis: int): {axis: [keyarr, indexer]}, copy=True, allow_dups=True ) - def _validate_read_indexer(self, key, indexer, axis, raise_missing=False): + def _validate_read_indexer( + self, key, indexer, axis: int, raise_missing: bool = False + ): """ Check that indexer can be used to return a result (e.g. at least one element was found, unless the list of keys was actually empty). @@ -1216,7 +1212,9 @@ def _validate_read_indexer(self, key, indexer, axis, raise_missing=False): if not (ax.is_categorical() or ax.is_interval()): warnings.warn(_missing_key_warning, FutureWarning, stacklevel=6) - def _convert_to_indexer(self, obj, axis=None, is_setter=False, raise_missing=False): + def _convert_to_indexer( + self, obj, axis: int, is_setter: bool = False, raise_missing: bool = False + ): """ Convert indexing key into something we can use to do actual fancy indexing on an ndarray @@ -1231,9 +1229,6 @@ def _convert_to_indexer(self, obj, axis=None, is_setter=False, raise_missing=Fal raise AmbiguousIndexError with integer labels? - No, prefer label-based indexing """ - if axis is None: - axis = self.axis or 0 - labels = self.obj._get_axis(axis) if isinstance(obj, slice): @@ -1362,7 +1357,7 @@ def __init__(self, name, obj): super().__init__(name, obj) @Appender(_NDFrameIndexer._validate_key.__doc__) - def _validate_key(self, key, axis): + def _validate_key(self, key, axis: int): if isinstance(key, slice): return True @@ -1378,7 +1373,7 @@ def _validate_key(self, key, axis): return True - def _convert_for_reindex(self, key, axis=None): + 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). @@ -1394,9 +1389,6 @@ def _convert_for_reindex(self, key, axis=None): ------- list-like of labels """ - - if axis is None: - axis = self.axis or 0 labels = self.obj._get_axis(axis) if com.is_bool_indexer(key): @@ -1726,7 +1718,7 @@ class _LocIndexer(_LocationIndexer): _exception = KeyError @Appender(_NDFrameIndexer._validate_key.__doc__) - def _validate_key(self, key, axis): + def _validate_key(self, key, axis: int): # valid for a collection of labels (we check their presence later) # slice of labels (where start-end in labels) @@ -2006,7 +1998,7 @@ class _iLocIndexer(_LocationIndexer): _exception = IndexError _get_slice_axis = _NDFrameIndexer._get_slice_axis - def _validate_key(self, key, axis): + def _validate_key(self, key, axis: int): if com.is_bool_indexer(key): if hasattr(key, "index") and isinstance(key.index, Index): if key.index.inferred_type == "integer": @@ -2132,7 +2124,7 @@ def _getitem_tuple(self, tup): return retval - def _get_list_axis(self, key, axis=None): + def _get_list_axis(self, key, axis: int): """ Return Series values by list or array of integers @@ -2145,8 +2137,6 @@ def _get_list_axis(self, key, axis=None): ------- Series object """ - if axis is None: - axis = self.axis or 0 try: return self.obj._take(key, axis=axis) except IndexError: @@ -2184,10 +2174,11 @@ def _getitem_axis(self, key, axis=None): return self._get_loc(key, axis=axis) - def _convert_to_indexer(self, obj, axis=None, is_setter=False): + # raise_missing is included for compat with the parent class signature + def _convert_to_indexer( + self, obj, axis: int, is_setter: bool = False, raise_missing: bool = False + ): """ much simpler as we only have to deal with our valid types """ - if axis is None: - axis = self.axis or 0 # make need to convert a float key if isinstance(obj, slice): @@ -2209,7 +2200,7 @@ def _convert_to_indexer(self, obj, axis=None, is_setter=False): class _ScalarAccessIndexer(_NDFrameIndexer): """ access scalars quickly """ - def _convert_key(self, key, is_setter=False): + def _convert_key(self, key, is_setter: bool = False): return list(key) def __getitem__(self, key): @@ -2289,7 +2280,7 @@ class _AtIndexer(_ScalarAccessIndexer): _takeable = False - def _convert_key(self, key, is_setter=False): + def _convert_key(self, key, is_setter: bool = False): """ require they keys to be the same type as the index (so we don't fallback) """ @@ -2366,7 +2357,7 @@ class _iAtIndexer(_ScalarAccessIndexer): def _has_valid_setitem_indexer(self, indexer): self._has_valid_positional_setitem_indexer(indexer) - def _convert_key(self, key, is_setter=False): + def _convert_key(self, key, is_setter: bool = False): """ require integer args (and convert to label arguments) """ for a, i in zip(self.obj.axes, key): if not is_integer(i): diff --git a/pandas/core/internals/blocks.py b/pandas/core/internals/blocks.py index 1e84437f5c2fc..f931df25c4fd5 100644 --- a/pandas/core/internals/blocks.py +++ b/pandas/core/internals/blocks.py @@ -2249,9 +2249,9 @@ def _can_hold_element(self, element): tipo = maybe_infer_dtype_type(element) if tipo is not None: return tipo == _NS_DTYPE or tipo == np.int64 - if isinstance(element, datetime): + elif isinstance(element, datetime): return element.tzinfo is None - if is_integer(element): + elif is_integer(element): return element == tslibs.iNaT # TODO: shouldnt we exclude timedelta64("NaT")? See GH#27297 @@ -2607,7 +2607,7 @@ def _can_hold_element(self, element): tipo = maybe_infer_dtype_type(element) if tipo is not None: return issubclass(tipo.type, (np.timedelta64, np.int64)) - if element is NaT: + elif element is NaT: return True return is_integer(element) or isinstance( element, (timedelta, np.timedelta64, np.int64) diff --git a/pandas/io/pytables.py b/pandas/io/pytables.py index 9206463e18fb3..1db177d792401 100644 --- a/pandas/io/pytables.py +++ b/pandas/io/pytables.py @@ -3974,6 +3974,7 @@ def process_filter(field, filt): for axis_name in obj._AXIS_NAMES.values(): axis_number = obj._get_axis_number(axis_name) axis_values = obj._get_axis(axis_name) + assert axis_number is not None # see if the field is the name of an axis if field == axis_name: diff --git a/pandas/tests/arithmetic/test_numeric.py b/pandas/tests/arithmetic/test_numeric.py index 1fbecbab469e4..2baee8bbe27a6 100644 --- a/pandas/tests/arithmetic/test_numeric.py +++ b/pandas/tests/arithmetic/test_numeric.py @@ -881,13 +881,13 @@ def check(series, other): _check_op(series, other, operator.pow, pos_only=True) - _check_op(series, other, lambda x, y: operator.add(y, x)) - _check_op(series, other, lambda x, y: operator.sub(y, x)) - _check_op(series, other, lambda x, y: operator.truediv(y, x)) - _check_op(series, other, lambda x, y: operator.floordiv(y, x)) - _check_op(series, other, lambda x, y: operator.mul(y, x)) - _check_op(series, other, lambda x, y: operator.pow(y, x), pos_only=True) - _check_op(series, other, lambda x, y: operator.mod(y, x)) + _check_op(series, other, ops.radd) + _check_op(series, other, ops.rsub) + _check_op(series, other, ops.rtruediv) + _check_op(series, other, ops.rfloordiv) + _check_op(series, other, ops.rmul) + _check_op(series, other, ops.rpow, pos_only=True) + _check_op(series, other, ops.rmod) tser = tm.makeTimeSeries().rename("ts") check(tser, tser * 2) diff --git a/pandas/tests/frame/test_indexing.py b/pandas/tests/frame/test_indexing.py index 3c102f49c6cbf..ae24ad65d2c56 100644 --- a/pandas/tests/frame/test_indexing.py +++ b/pandas/tests/frame/test_indexing.py @@ -1680,6 +1680,7 @@ def test_setitem_single_column_mixed_datetime(self): df.loc["d", :] = np.nan assert not isna(df.loc["c", :]).all() + # FIXME: don't leave commented-out # as of GH 3216 this will now work! # try to set with a list like item # pytest.raises( diff --git a/pandas/tests/series/test_operators.py b/pandas/tests/series/test_operators.py index 0c25df7997469..062c07cb6242a 100644 --- a/pandas/tests/series/test_operators.py +++ b/pandas/tests/series/test_operators.py @@ -692,10 +692,7 @@ def test_operators_corner(self): ) tm.assert_series_equal(added[:-5], expected) - pairings = [ - (Series.div, operator.truediv, 1), - (Series.rdiv, lambda x, y: operator.truediv(y, x), 1), - ] + pairings = [(Series.div, operator.truediv, 1), (Series.rdiv, ops.rtruediv, 1)] for op in ["add", "sub", "mul", "pow", "truediv", "floordiv"]: fv = 0 lop = getattr(Series, op) diff --git a/pandas/tests/sparse/series/test_series.py b/pandas/tests/sparse/series/test_series.py index ad4c898b004ac..899752cde54ed 100644 --- a/pandas/tests/sparse/series/test_series.py +++ b/pandas/tests/sparse/series/test_series.py @@ -12,6 +12,7 @@ import pandas as pd from pandas import DataFrame, Series, SparseDtype, SparseSeries, bdate_range, isna +from pandas.core import ops from pandas.core.reshape.util import cartesian_product import pandas.core.sparse.frame as spf from pandas.tests.series.test_api import SharedWithSparse @@ -572,16 +573,16 @@ def check(a, b): _check_op(a, b, operator.floordiv) _check_op(a, b, operator.mul) - _check_op(a, b, lambda x, y: operator.add(y, x)) - _check_op(a, b, lambda x, y: operator.sub(y, x)) - _check_op(a, b, lambda x, y: operator.truediv(y, x)) - _check_op(a, b, lambda x, y: operator.floordiv(y, x)) - _check_op(a, b, lambda x, y: operator.mul(y, x)) + _check_op(a, b, ops.radd) + _check_op(a, b, ops.rsub) + _check_op(a, b, ops.rtruediv) + _check_op(a, b, ops.rfloordiv) + _check_op(a, b, ops.rmul) # FIXME: don't leave commented-out # NaN ** 0 = 1 in C? # _check_op(a, b, operator.pow) - # _check_op(a, b, lambda x, y: operator.pow(y, x)) + # _check_op(a, b, ops.rpow) check(self.bseries, self.bseries) check(self.iseries, self.iseries)