Repository: pandas-dev/pandas

Issue:
BUG: coercing of bools in groupby transform
#### Code Sample
```python
df = pd.DataFrame({'A': [1.1,2.2], 'B':[1,2]})
df.groupby('B').A.transform(lambda x: True)
```
This returns
```
Out[3]:
0    1.0
1    1.0
Name: A, dtype: float64
```
#### Problem 
`groupby.transform` returns numeric values, not __bool__ . This is inconsistent
because `DataFrame.transform` behaves differently:

```python
In [5]: df.A.transform(lambda x:True)
Out[5]:
0    True
1    True
Name: A, dtype: bool
```
#### Additional

But please note that if the original data type is `int`, it works properly:
```python
In [9]: df = pd.DataFrame({'A': [1,2], 'B':[1,2]})
   ...: df.groupby('B').A.transform(lambda x: True)
   ...:
Out[9]:
0    True
1    True
Name: A, dtype: bool
```


Discussion:
Looks essentially the same as #10972, which was closed by #15430, but apparently didn't capture this case.  `apply` does do the right inference here:

```
In [2]: df.groupby('B').A.apply(lambda x: True)
Out[2]:
B
1    True
2    True
Name: A, dtype: bool
```

Resolving patch:
diff --git a/pandas/core/dtypes/cast.py b/pandas/core/dtypes/cast.py
--- a/pandas/core/dtypes/cast.py
+++ b/pandas/core/dtypes/cast.py
@@ -110,9 +110,7 @@ def trans(x):  # noqa
                     np.prod(result.shape)):
                 return result
 
-        if issubclass(dtype.type, np.floating):
-            return result.astype(dtype)
-        elif is_bool_dtype(dtype) or is_integer_dtype(dtype):
+        if is_bool_dtype(dtype) or is_integer_dtype(dtype):
 
             # if we don't have any elements, just astype it
             if not np.prod(result.shape):
@@ -144,6 +142,9 @@ def trans(x):  # noqa
                     # hit here
                     if (new_result == result).all():
                         return new_result
+        elif (issubclass(dtype.type, np.floating) and
+                not is_bool_dtype(result.dtype)):
+            return result.astype(dtype)
 
         # a datetimelike
         # GH12821, iNaT is casted to float


Test patch:
diff --git a/pandas/tests/dtypes/test_cast.py b/pandas/tests/dtypes/test_cast.py
--- a/pandas/tests/dtypes/test_cast.py
+++ b/pandas/tests/dtypes/test_cast.py
@@ -9,7 +9,7 @@
 from datetime import datetime, timedelta, date
 import numpy as np
 
-from pandas import Timedelta, Timestamp, DatetimeIndex, DataFrame, NaT
+from pandas import Timedelta, Timestamp, DatetimeIndex, DataFrame, NaT, Series
 
 from pandas.core.dtypes.cast import (
     maybe_downcast_to_dtype,
@@ -45,6 +45,12 @@ def test_downcast_conv(self):
         expected = np.array([8, 8, 8, 8, 9])
         assert (np.array_equal(result, expected))
 
+        # GH16875 coercing of bools
+        ser = Series([True, True, False])
+        result = maybe_downcast_to_dtype(ser, np.dtype(np.float64))
+        expected = ser
+        tm.assert_series_equal(result, expected)
+
         # conversions
 
         expected = np.array([1, 2])
diff --git a/pandas/tests/groupby/test_transform.py b/pandas/tests/groupby/test_transform.py
--- a/pandas/tests/groupby/test_transform.py
+++ b/pandas/tests/groupby/test_transform.py
@@ -195,6 +195,19 @@ def test_transform_bug(self):
         expected = Series(np.arange(5, 0, step=-1), name='B')
         assert_series_equal(result, expected)
 
+    def test_transform_numeric_to_boolean(self):
+        # GH 16875
+        # inconsistency in transforming boolean values
+        expected = pd.Series([True, True], name='A')
+
+        df = pd.DataFrame({'A': [1.1, 2.2], 'B': [1, 2]})
+        result = df.groupby('B').A.transform(lambda x: True)
+        assert_series_equal(result, expected)
+
+        df = pd.DataFrame({'A': [1, 2], 'B': [1, 2]})
+        result = df.groupby('B').A.transform(lambda x: True)
+        assert_series_equal(result, expected)
+
     def test_transform_datetime_to_timedelta(self):
         # GH 15429
         # transforming a datetime to timedelta