Skip to content

Issue #59098: fix bug for default level behavior in xs function #59493

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

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions doc/source/whatsnew/v3.0.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,24 @@ These improvements also fixed certain bugs in groupby:
- :meth:`.DataFrameGroupBy.sum` would have incorrect values when there are multiple groupings, unobserved groups, and non-numeric data (:issue:`43891`)
- :meth:`.DataFrameGroupBy.value_counts` would produce incorrect results when used with some categorical and some non-categorical groupings and ``observed=False`` (:issue:`56016`)

.. _whatsnew_300.notable_bug_fixes.xs_function_default_level:

`DataFrame.xs()` did not work as expected when level was not specified by default. (:issue:`59098`)

ex.
.. ipython:: python

df = pd.DataFrame(dict(i=[1,2,3], j=[1,1,2], x=[10, 100, 1000])).set_index(["i", "j"])

key = (1, 1)

# Returns DataFrame as expected:
result1 = df.xs(key, drop_level=False, level=list(range(len(key))))

# Returns Series, but DataFrame was expected:
result2 = df.xs(key, drop_level=False)


.. _whatsnew_300.notable_bug_fixes.notable_bug_fix2:

notable_bug_fix2
Expand Down
8 changes: 7 additions & 1 deletion pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from __future__ import annotations

import collections
import collections.abc
from copy import deepcopy
import datetime as dt
from functools import partial
Expand Down Expand Up @@ -4126,7 +4127,12 @@ class animal locomotion
index = self.index

if isinstance(index, MultiIndex):
loc, new_index = index._get_loc_level(key, level=0)
level = range(len(key)) if isinstance(key, collections.abc.Sequence) else 0
loc, new_index = index.get_loc_level(
key,
level=level,
drop_level=drop_level
)
if not drop_level:
if lib.is_integer(loc):
# Slice index must be an integer or None
Expand Down
16 changes: 16 additions & 0 deletions pandas/tests/series/indexing/test_xs.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import pytest

from pandas import (
DataFrame,
MultiIndex,
Series,
date_range,
Expand Down Expand Up @@ -80,3 +81,18 @@ def test_xs_key_as_list(self):

with pytest.raises(TypeError, match="list keys are not supported"):
ser.xs(["a"], axis=0, drop_level=False)

def test_xs_default_level(self):
# GH#59098
df = DataFrame(
{"i": [1,2,3], "j": [1,1,2], "x": [10, 100, 1000]}
).set_index(["i", "j"])
key = (1, 1)

# Both scenarios should return DataFrame
result_with_level = df.xs(key, drop_level=False, level=list(range(len(key))))
result_with_default = df.xs(key, drop_level=False)

assert type(result_with_default) == DataFrame
assert type(result_with_level) == type(result_with_default)
tm.assert_equal(result_with_level, result_with_default)
Loading