Repository: pandas-dev/pandas

Issue:
DataFrame.gropuby().mean() incorrect result

Anybody knows why I'm having different results when I apply the same operator to the same DataFrame but using groupby? 
When using groupby , It returned negative values while all values are positive.
```
from pandas import DataFrame
df = DataFrame({"user":["A", "A", "A", "A", "A"],
                            "connections":[18446744073699999744, 4970, 4749, 4719, 4704]})

df.mean()
```
connections    3.689349e+18
dtype: float64
```
df.groupby("user")["connections"].mean()
```
user
A   -1906546.0
Name: connections, dtype: float64


INSTALLED VERSIONS
------------------
commit: None
python: 3.6.5.final.0
python-bits: 64
OS: Windows
OS-release: 10
machine: AMD64
processor: Intel64 Family 6 Model 142 Stepping 9, GenuineIntel
byteorder: little
LC_ALL: None
LANG: None
LOCALE: None.None

pandas: 0.23.0
pytest: 3.5.1
pip: 10.0.1
setuptools: 39.1.0
Cython: 0.28.2
numpy: 1.14.3
scipy: 1.1.0
pyarrow: None
xarray: None
IPython: 6.4.0
sphinx: 1.7.4
patsy: 0.5.0
dateutil: 2.7.3
pytz: 2018.4
blosc: None
bottleneck: 1.2.1
tables: 3.4.3
numexpr: 2.6.5
feather: None
matplotlib: 2.2.2
openpyxl: 2.5.3
xlrd: 1.1.0
xlwt: 1.3.0
xlsxwriter: 1.0.4
lxml: 4.2.1
bs4: 4.6.0
html5lib: 1.0.1
sqlalchemy: 1.2.7
pymysql: None
psycopg2: None
jinja2: 2.10
s3fs: None
fastparquet: None
pandas_gbq: None
pandas_datareader: None



Discussion:
Can you try on master? Looks like an int overflow somewhere if still present investigation and PRs are always welcome
Hi WillAyd, thanks for your prompt response.  This is the first time I post an issue. Could you please explain little further what you exactly mean by   "try on master" ? Thanks in advance!
I've upgraded to latest version and the problem still persists. In the investigation line that WillAyd suggests, the same example whit float numbers worked fine.

```
df = DataFrame({"user":["A", "A", "A", "A", "A"],
           "connections":[18446744073699999744.0, 4970.0, 4749.0, 4719.0, 4704.0]})

df.mean()
connections    3.689349e+18
dtype: float64

df.groupby("user")["connections"].mean()
user
A    3.689349e+18
Name: connections, dtype: float64

df.mean()[0] == df.groupby("user")["connections"].mean()[0]
True

```

Resolving patch:
diff --git a/pandas/core/dtypes/common.py b/pandas/core/dtypes/common.py
--- a/pandas/core/dtypes/common.py
+++ b/pandas/core/dtypes/common.py
@@ -90,6 +90,33 @@ def ensure_categorical(arr):
     return arr
 
 
+def ensure_int64_or_float64(arr, copy=False):
+    """
+    Ensure that an dtype array of some integer dtype
+    has an int64 dtype if possible
+    If it's not possible, potentially because of overflow,
+    convert the array to float64 instead.
+
+    Parameters
+    ----------
+    arr : array-like
+          The array whose data type we want to enforce.
+    copy: boolean
+          Whether to copy the original array or reuse
+          it in place, if possible.
+
+    Returns
+    -------
+    out_arr : The input array cast as int64 if
+              possible without overflow.
+              Otherwise the input array cast to float64.
+    """
+    try:
+        return arr.astype('int64', copy=copy, casting='safe')
+    except TypeError:
+        return arr.astype('float64', copy=copy)
+
+
 def is_object_dtype(arr_or_dtype):
     """
     Check whether an array-like or dtype is of the object dtype.
diff --git a/pandas/core/groupby/ops.py b/pandas/core/groupby/ops.py
--- a/pandas/core/groupby/ops.py
+++ b/pandas/core/groupby/ops.py
@@ -23,6 +23,7 @@
     ensure_float64,
     ensure_platform_int,
     ensure_int64,
+    ensure_int64_or_float64,
     ensure_object,
     needs_i8_conversion,
     is_integer_dtype,
@@ -471,7 +472,7 @@ def _cython_operation(self, kind, values, how, axis, min_count=-1,
             if (values == iNaT).any():
                 values = ensure_float64(values)
             else:
-                values = values.astype('int64', copy=False)
+                values = ensure_int64_or_float64(values)
         elif is_numeric and not is_complex_dtype(values):
             values = ensure_float64(values)
         else:


Test patch:
diff --git a/pandas/tests/groupby/test_function.py b/pandas/tests/groupby/test_function.py
--- a/pandas/tests/groupby/test_function.py
+++ b/pandas/tests/groupby/test_function.py
@@ -1125,3 +1125,12 @@ def h(df, arg3):
     expected = pd.Series([4, 8, 12], index=pd.Int64Index([1, 2, 3]))
 
     tm.assert_series_equal(result, expected)
+
+
+def test_groupby_mean_no_overflow():
+    # Regression test for (#22487)
+    df = pd.DataFrame({
+        "user": ["A", "A", "A", "A", "A"],
+        "connections": [4970, 4749, 4719, 4704, 18446744073699999744]
+    })
+    assert df.groupby('user')['connections'].mean()['A'] == 3689348814740003840