Skip to content

Commit

Permalink
TYP: type NDFrame.(_get_axis|_get_axis_name|_get_axis_number) (#33610)
Browse files Browse the repository at this point in the history
  • Loading branch information
topper-123 authored Apr 18, 2020
1 parent b630cdb commit 4707d8e
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 19 deletions.
4 changes: 3 additions & 1 deletion doc/source/whatsnew/v1.1.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,9 @@ Other API changes
Backwards incompatible API changes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- :meth:`DataFrame.swaplevels` now raises a ``TypeError`` if the axis is not a :class:`MultiIndex`.
Previously a ``AttributeError`` was raised (:issue:`31126`)
Previously an ``AttributeError`` was raised (:issue:`31126`)
- :meth:`DataFrame.xs` now raises a ``TypeError`` if a ``level`` keyword is supplied and the axis is not a :class:`MultiIndex`.
Previously an ``AttributeError`` was raised (:issue:`33610`)
- :meth:`DataFrameGroupby.mean` and :meth:`SeriesGroupby.mean` (and similarly for :meth:`~DataFrameGroupby.median`, :meth:`~DataFrameGroupby.std` and :meth:`~DataFrameGroupby.var`)
now raise a ``TypeError`` if a not-accepted keyword argument is passed into it.
Previously a ``UnsupportedFunctionCall`` was raised (``AssertionError`` if ``min_count`` passed into :meth:`~DataFrameGroupby.median`) (:issue:`31485`)
Expand Down
36 changes: 18 additions & 18 deletions pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ def _construct_axes_from_arguments(
return axes, kwargs

@classmethod
def _get_axis_number(cls, axis):
def _get_axis_number(cls, axis) -> int:
axis = cls._AXIS_ALIASES.get(axis, axis)
if is_integer(axis):
if axis in cls._AXIS_NAMES:
Expand All @@ -366,7 +366,7 @@ def _get_axis_number(cls, axis):
raise ValueError(f"No axis named {axis} for object type {cls.__name__}")

@classmethod
def _get_axis_name(cls, axis):
def _get_axis_name(cls, axis) -> str:
axis = cls._AXIS_ALIASES.get(axis, axis)
if isinstance(axis, str):
if axis in cls._AXIS_NUMBERS:
Expand All @@ -378,12 +378,12 @@ def _get_axis_name(cls, axis):
pass
raise ValueError(f"No axis named {axis} for object type {cls.__name__}")

def _get_axis(self, axis):
def _get_axis(self, axis) -> Index:
name = self._get_axis_name(axis)
return getattr(self, name)

@classmethod
def _get_block_manager_axis(cls, axis):
def _get_block_manager_axis(cls, axis) -> int:
"""Map the axis to the block_manager axis."""
axis = cls._get_axis_number(axis)
if cls._AXIS_REVERSED:
Expand Down Expand Up @@ -590,7 +590,9 @@ def swapaxes(self: FrameOrSeries, axis1, axis2, copy=True) -> FrameOrSeries:
if copy:
new_values = new_values.copy()

return self._constructor(new_values, *new_axes).__finalize__(
# ignore needed because of NDFrame constructor is different than
# DataFrame/Series constructors.
return self._constructor(new_values, *new_axes).__finalize__( # type: ignore
self, method="swapaxes"
)

Expand Down Expand Up @@ -3491,6 +3493,8 @@ class animal locomotion
axis = self._get_axis_number(axis)
labels = self._get_axis(axis)
if level is not None:
if not isinstance(labels, MultiIndex):
raise TypeError("Index must be a MultiIndex")
loc, new_ax = labels.get_loc_level(key, level=level, drop_level=drop_level)

# create the tuple of the indexer
Expand Down Expand Up @@ -7628,11 +7632,11 @@ def at_time(
axis = self._get_axis_number(axis)

index = self._get_axis(axis)
try:
indexer = index.indexer_at_time(time, asof=asof)
except AttributeError as err:
raise TypeError("Index must be DatetimeIndex") from err

if not isinstance(index, DatetimeIndex):
raise TypeError("Index must be DatetimeIndex")

indexer = index.indexer_at_time(time, asof=asof)
return self._take_with_is_copy(indexer, axis=axis)

def between_time(
Expand Down Expand Up @@ -7711,16 +7715,12 @@ def between_time(
axis = self._get_axis_number(axis)

index = self._get_axis(axis)
try:
indexer = index.indexer_between_time(
start_time,
end_time,
include_start=include_start,
include_end=include_end,
)
except AttributeError as err:
raise TypeError("Index must be DatetimeIndex") from err
if not isinstance(index, DatetimeIndex):
raise TypeError("Index must be DatetimeIndex")

indexer = index.indexer_between_time(
start_time, end_time, include_start=include_start, include_end=include_end,
)
return self._take_with_is_copy(indexer, axis=axis)

def resample(
Expand Down
12 changes: 12 additions & 0 deletions pandas/tests/indexing/multiindex/test_xs.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,3 +243,15 @@ def test_series_getitem_multiindex_xs_by_label():

result = s.xs("one", level="L2")
tm.assert_series_equal(result, expected)


def test_xs_levels_raises():
df = DataFrame({"A": [1, 2, 3]})

msg = "Index must be a MultiIndex"
with pytest.raises(TypeError, match=msg):
df.xs(0, level="as")

s = df.A
with pytest.raises(TypeError, match=msg):
s.xs(0, level="as")

0 comments on commit 4707d8e

Please sign in to comment.