ENH: Let callables in .loc and .iloc take an optional axis parameter
State: closed

Currently, when supplying callables to ``.loc``and ``.iloc`` we can't know which axis the callable is supplied for. This makes is  difficult to make more general filtering callables, e.g. if we want the callable to filter over transposed axes.

This PR allows the callables supplied to ``.loc`` and ``.iloc`` to take either one or two arguments, instead of only one argument, as it could previously.

This PR is fully backwards compatible.

Labels:
name: Enhancement
name: Indexing
description: Related to indexing on series/frames, not to indexes themselves

Comments:
Maybe I'm missing something, but isn't the axis always obvious based on where you place the function in .loc or .iloc?

- df.loc[f] -> axis is 0
- df.loc[:, f] -> axis is 1
- df.loc[f, f] -> axis is 0 for first, 1 for second

So can't you currently get this behavior with

- df.loc[lambda x: f(x, 0)]
- df.loc[:, lambda x: f(x, 1)]
- df.loc[lambda x: f(x, 0), lambda x: f(x, 1)]

? Is there some use case I'm missing?
> Maybe I'm missing something, but isn't the axis always obvious based on where you place the function in .loc or .iloc?
> 
> * df.loc[f] -> axis is 0
> * df.loc[:, f] -> axis is 1
> * df.loc[f, f] -> axis is 0 for first, 1 for second
> 
> So can't you currently get this behavior with
> 
> * df.loc[lambda x: f(x, 0)]
> * df.loc[lambda x: f(x, 1)]
> * df.loc[lambda x: f(x, 0), lambda x: f(x, 1)]
> 
> ? Is there some use case I'm missing?

agreed, this seems to be an extension that warrants test and maintenance when the underlying application is quite easy as above?
This is obviously intended for more complex workflows than lambdas, specifically for situations where the callable needs to know if it is supplied to the first axis or second axis, so we can know the correct filtering direction. This will allow for more composable code, which is good.

I don't agree this adds any maintenance really, it is just using ``apply_maybe_callable_with_axis`` instead of ``apply_if_callable``, so quite minor. The bulk of this PR is tests and docs, not actual code.

I agree that this isn't a huge maintenance addition, but always the goal should be to keep things slim. Tests and docs also require maintenance, to be fair. If this solves a large enough problem though then I think this cost is worth it.

Do you have a specific example where the callable needs to know the axis at run time (ie it is impossible to know the axis when you supply the function)? Sorry to be skeptical, I know it's not fun for you to have to fight for this change. Thank you!
Hey @topper-123 👋 , I notice you are still working on this PR. I'm not a maintainer of pandas at all, so not sure exactly what the process should look like, but you might want to get some initial confirmation from a maintainer that this is headed in the right direction. Otherwise you are running the risk that you're putting this great effort in, and then at the end they might not accept it. I know I've done that many times before and it is pretty disheartening, so I just wanted to give you a heads up. Sorry, not trying to be a downer, trying to improve things and writing PRs is a lot of work, so thank you!
Thanks for the PR, but it appears there's some discussion needed first in an enhancement issue as there's not a lot of buy in yet (I would be -0 but could be convinced otherwise). Since this PR hasn't been getting a lot of traction, closing for now, but we can reopen if there is more support in an enhancement issue from the team.