PERF: groupby with string dtype
State: closed

- [x] closes #41596 
- [ ] tests added / passed
- [x] Ensure all linting tests pass, see [here](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#pre-commit) for how to run them
- [x] whatsnew entry

```python
In [1]: import numpy as np
   ...:    ...: import pandas as pd
   ...:    ...: pd.__version__
   ...:    ...:
   ...:    ...: cols = list('abcdefghjkl')
   ...:    ...: df = pd.DataFrame(np.random.randint(0, 100, size=(100, len(cols))), columns=cols)
   ...:    ...: df_str = df.astype(str)
   ...:    ...: df_string = df.astype('string')

In [2]: %timeit df_str.groupby('a')[cols[1:]].last()
2.88 ms ± 70.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [3]: %timeit df_string.groupby('a')[cols[1:]].last()
3.27 ms ± 12.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)  #PR
54.4 ms ± 244 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)    #master

Labels:
name: Groupby
name: Performance
description: Memory or execution speed performance
name: Regression
description: Functionality that used to work in a prior pandas version
name: Strings
description: String extension data type and string data

Comments:
does this also fix the case mentioned in https://github.com/pandas-dev/pandas/issues/41596#issuecomment-854628297? if so can you post the timings for that too for df_str.groupby('a')[cols[1:]].last() on master and with this PR
Hi @simonjayhawkins - no this PR doesn't address the performance slowdown in the `object` dtype.
It only ensures that `string` takes the cython-path (similar to the `object` dtype).

Also note, that I have changed the size of the `df` in the top comment, wrt the example in the bug report.
That's okay, but we can't close that issue. will need to open a new one specifically for that case, (regression between 1.2.5 and 1.3) or change the OP to read "xref" instead of "closes"

out of curiosity, did you identify which commit caused the slowdown between 1.1.5 and 1.2?
Updated the top comment. 
Honestly, I didn't try to find the commit. This fix was suggested in a comment in the bug report.
So why do we need to special case an specific EA dtype? (Maybe this was done before). In general EA handling should be more generic.
I think the current implementation of `_ea_wrap_cython_operation` works that way, no?

I can see a TODO for a more generic approach.
yes, it appears that there is intent to make `_ea_wrap_cython_operation` more generic. I'm just wondering why it worked in 1.1.5
can you merge master to fix doc build #43688
> That's okay, but we can't close that issue. will need to open a new one specifically for that case, (regression between 1.2.5 and 1.3) or change the OP to read "xref" instead of "closes"

changed back to "closes" xref https://github.com/pandas-dev/pandas/issues/41596#issuecomment-924080060
> groupby.String.time_str_func: setup: wrong number of arguments (for <bound method String.setup of <benchmarks.groupby.String object at 0x7f6c8c634a30>> in groupby.py:626): expected 2, has 1

in the asvs
also merge master as the deprecation warnings on asv's are silenced now
seems still some CI / checks are failing, also make sure you merge `upstream/master` as the patch for some of the deprecation warnings in asv's was not pulled in.
thanks @debnathshoham very nice!
Owee, I'm MrMeeseeks, Look at me.

There seem to be a conflict, please backport manually. Here are approximate instructions:

1. Checkout backport branch and update it.

```
$ git checkout 1.3.x
$ git pull
```

2. Cherry pick the first parent branch of the this PR on top of the older branch:
```
$ git cherry-pick -m1 b3e9ae715ab908a9735401d8164da505a293d3c6
```

3. You will likely have some merge/cherry-pick conflict here, fix them and commit:

```
$ git commit -am 'Backport PR #43634: PERF: groupby with string dtype'
```

4. Push to a named branch :

```
git push YOURFORK 1.3.x:auto-backport-of-pr-43634-on-1.3.x
```

5. Create a PR against branch 1.3.x, I would have named this PR:

> "Backport PR #43634 on branch 1.3.x (PERF: groupby with string dtype)"

And apply the correct labels and milestones.

Congratulation you did some good work! Hopefully your backport PR will be tested by the continuous integration and merged soon!

Remember to remove `Still Needs Manual Backport` label once the PR gets merged.

If these instruction are inaccurate, feel free to [suggest an improvement](https://github.com/MeeseeksBox/MeeseeksDev).
                
@meeseeksdev backport 1.3.x
Owee, I'm MrMeeseeks, Look at me.

There seem to be a conflict, please backport manually. Here are approximate instructions:

1. Checkout backport branch and update it.

```
$ git checkout 1.3.x
$ git pull
```

2. Cherry pick the first parent branch of the this PR on top of the older branch:
```
$ git cherry-pick -m1 b3e9ae715ab908a9735401d8164da505a293d3c6
```

3. You will likely have some merge/cherry-pick conflict here, fix them and commit:

```
$ git commit -am 'Backport PR #43634: PERF: groupby with string dtype'
```

4. Push to a named branch :

```
git push YOURFORK 1.3.x:auto-backport-of-pr-43634-on-1.3.x
```

5. Create a PR against branch 1.3.x, I would have named this PR:

> "Backport PR #43634 on branch 1.3.x (PERF: groupby with string dtype)"

And apply the correct labels and milestones.

Congratulation you did some good work! Hopefully your backport PR will be tested by the continuous integration and merged soon!

Remember to remove `Still Needs Manual Backport` label once the PR gets merged.

If these instruction are inaccurate, feel free to [suggest an improvement](https://github.com/MeeseeksBox/MeeseeksDev).
                
@debnathshoham if you wouldn't mind following the procedure above to backport