Bug in xs raising KeyError for MultiIndex columns with droplevel False and list indexe
State: closed

- [x] closes #41760
- [x] tests added / passed
- [x] Ensure all linting tests pass, see [here](https://pandas.pydata.org/pandas-docs/dev/development/contributing.html#code-standards) for how to run them
- [x] whatsnew entry

cc @simonjayhawkins Should we include in 1.2.5 or push to 1.3?

Labels:
name: Indexing
description: Related to indexing on series/frames, not to indexes themselves
name: Regression
description: Functionality that used to work in a prior pandas version

Comments:
> cc @simonjayhawkins Should we include in 1.2.5 or push to 1.3?

this seems backportable. will run a bisect on the issue to get some more context.
@phofl is this a bug or is the user expecting output that may have been incorrect in 1.1.5.

IIUC key is an index label or tuple of index label.

if a tuple, represents more than one level of the index to match.

a list should not be an allowable input. As a sequence should it be treated as a tuple and raise KeyError as it does now in 1.2.x/master.

or should we validate the key and raise TypeError?
Good point, thanks for bringing this up. You are correct this should not work at all.

In general I think a list is counterintuitive as an input, because in loc/iloc we treat list as single level indexers, so we should disallow them? We have one test using this, but there are two levels given, so it is implicitly clear, that the user tries to use the list elements on different levels ``df.xs([2008, "sat"], level=["year", "day"], drop_level=False)``.

So for the reason of backwarts compatibility we should probably raise, if a list is given and the number of levels does not match the length of the list (like in this case)?

I am not really happy with the list case above, but we probably have to deprecate instead of removing outright.
> Good point, thanks for bringing this up. You are correct this should not work at all.
> 
> In general I think a list is counterintuitive as an input, because in loc/iloc we treat list as single level indexers, so we should disallow them? We have one test using this, but there are two levels given, so it is implicitly clear, that the user tries to use the list elements on different levels `df.xs([2008, "sat"], level=["year", "day"], drop_level=False)`.
> 
> So for the reason of backwarts compatibility we should probably raise, if a list is given and the number of levels does not match the length of the list (like in this case)?
> 
> I am not really happy with the list case above, but we probably have to deprecate instead of removing outright.

I agree that we should remove this case. Can you add a deprecation warning in this cse? if so then ok to backport. (.xs is itself kind of janky anyhow), though we don't allow `drop_level` via `.loc`.....
cc @jbrockmendel if comments here
>  We have one test using this, but there are two levels given, so it is implicitly clear, that the user tries to use the list elements on different levels df.xs([2008, "sat"], level=["year", "day"], drop_level=False).

So the idea is that we would deprecate allowing this so the user would need to pass either `(2008, "sat")` or `[(2008, "sat")]`?

> though we don't allow drop_level via .loc.....

xref #35418 but i dont think there's any appetite for making loc more complicated
Yes, disallowing lists completly, e.g. user has to pass ``(2008, "sat")``. 
> Yes, disallowing lists completly, e.g. user has to pass (2008, "sat").

im on board
Will repurpose this pr with the changes
Deprecated list as key with same length as level and raised when key has different length than level.

Added the whatsnew to 1.3. Would move if we want to backport this?
> Deprecated list as key with same length as level and raised when key has different length than level.
> 
> Added the whatsnew to 1.3. Would move if we want to backport this?

this is ok to backport i think
Moved whatsnew
@meeseeksdev backport 1.2.x
thanks @phofl 
Something went wrong ... Please have  a look at my logs.