Do not cast .transform() output back to input dtype (closes #10972)
State: closed

 - [x] closes #10972
 - [x] tests added / passed
 - [x] passes ``git diff upstream/master | flake8 --diff``
 - [x] whatsnew entry

Maybe need more tests, and check performance?

Labels:
name: Bug
name: Groupby
name: Dtype Conversions
description: Unexpected or buggy dtype conversions

Comments:
Well, each time I run asv, I get different results, but after closing everything and leaving my computer alone, here is what I get:
```
   before     after       ratio
  [3853fe6d] [2bc47491]
+   19.84ms    22.47ms      1.13  groupby.GroupBySuite.time_diff('float', 100)
+   12.45ms    13.92ms      1.12  groupby.FirstLast.time_groupby_nth_none('float64')
-    1.97ms     1.78ms      0.90  groupby.GroupBySuite.time_size('int', 10000)
-   27.05ms    24.28ms      0.90  groupby.GroupBySuite.time_rank('float', 100)
-   19.79ms    17.21ms      0.87  groupby.FirstLast.time_groupby_nth_none('object')
-   18.12ms    15.64ms      0.86  groupby.FirstLast.time_groupby_nth_none('datetime')
-   10.96ms     9.37ms      0.86  groupby.FirstLast.time_groupby_last('datetime')
```
those are not the transform asv 
I run `asv continuous -f 1.1 -E virtualenv upstream/master HEAD -b ^groupby`, but it's the first time I do perf, so I may have missed something :)

Is there something else I should do for this PR?
I think Appveyor is complaining about int being int32 on windows instead of int64. Is there a way to cast them to int64 instead?
# [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/15256?src=pr&el=h1) Report
> Merging [#15256](https://codecov.io/gh/pandas-dev/pandas/pull/15256?src=pr&el=desc) into [master](https://codecov.io/gh/pandas-dev/pandas/commit/c26e5bbed826aaf9a643c604f7f754f29af4bd64?src=pr&el=desc) will **not impact** coverage.


```diff
@@           Coverage Diff           @@
##           master   #15256   +/-   ##
=======================================
  Coverage   86.33%   86.33%           
=======================================
  Files         139      139           
  Lines       51149    51149           
=======================================
  Hits        44157    44157           
  Misses       6992     6992
```


| [Impacted Files](https://codecov.io/gh/pandas-dev/pandas/pull/15256?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pandas/core/groupby.py](https://codecov.io/gh/pandas-dev/pandas/compare/c26e5bbed826aaf9a643c604f7f754f29af4bd64...40cfe909f3d8d17ba5ed30f2d7b9885960a49b55?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvZ3JvdXBieS5weQ==) | `95.15% <100%> (ø)` | :white_check_mark: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/15256?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/15256?src=pr&el=footer). Last update [c26e5bb...ec52ab4](https://codecov.io/gh/pandas-dev/pandas/compare/c26e5bbed826aaf9a643c604f7f754f29af4bd64...ec52ab4015cf046ed752de887063d0c587ff4755?el=footer&src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).
@jreback Hum, this is more complex than I thought

The initial problem is: `.transform` cast output dtypes back to input dtype, so `.size` for instance produce timestamps if the initial data was timestamps

If I keep the output type as it is, then `Series.mean`, for instance, will produce `float`. So if the original data is `float32`,  performing `.groupby().apply(lambda g: g.mean())`  might thus result in `float64` output, but `.groupby().mean()` will stay in `float32`.

Am I missing something obvious? How to proceed from there?
you need to selectively cast

all lost every function should be cast except for things that produce ints (like size)
So `.groupby().agg(lambda : float(len(x)))` should keep producing timestamps if input is timestamps?

(That's how I stumbled on this issue when working on my PR #12607)
@nbonnotte of course not, that's the point of this issue!

you simply need to infer based on the return values, not automatically cast it.

you *might* be able to simply stick it into a Series and it will work, BUT, you will still need to cast if its a numeric type (IOW a float) to the original type flavor.

my points above is that you need to really look at the tests create code that DOESN't change anything except for specific tests (e.g. the test from the actual issue). 
Ok. I'm going to take it slow, starting with datetime input
this was fixed by https://github.com/pandas-dev/pandas/commit/251826f0861159160bd1d51eafadb6e0b4161f77
It looks so simple once you see the solution... Thanks @jreback for your feedback and your patience, sorry I couldn't get that through