Repository: pandas-dev/pandas
Pull request: BUG: Issue #29128 Series.var not returning the correct result
- [ x ] closes #29128
- [ x ] tests added / passed
- [ x ] passes `black pandas`
- [ x ] passes `git diff upstream/master -u -- "*.py" | flake8 --diff`
- [ x ] whatsnew entry

This PR closes https://github.com/pandas-dev/pandas/issues/29128

Problem statement:
Variance of nullable Int64 ignores ddof argument
Variance calculation `Series.var()` is ignoring the `ddof` argument for nullable integer type `Int64`. Behavior should match that of `float` type.

```python
>>> pd.__version__
'0.25.1'
>>> np.__version__
'1.17.2'
>>> s1 = pd.Series(data=[1,2,3,4,5,6,np.nan,np.nan])
>>> series.var(ddof=0)
3.5
>>> s1 = pd.Series(data=[1,2,3,4,5,6,np.nan,np.nan])
>>> s1.var(ddof=0)
2.9166666666666665
>>> s1.var(ddof=1)
3.5
>>> s2 = pd.Series(data=[1,2,3,4,5,6,np.nan,np.nan], dtype="Int64")
>>> s2.var(ddof=0)
3.5
>>> s2.var(ddof=1)
3.5 
```

Hints from issue discussion:
@VictorDavis thanks for the report! 
From a quick look, it seems the argument is not passed through, here:

https://github.com/pandas-dev/pandas/blob/6c898e6a58285c841511e853bb1bf8a90766df78/pandas/core/arrays/integer.py#L655

Commit message: test modified

Patch to review:
diff --git a/doc/source/whatsnew/v1.0.0.rst b/doc/source/whatsnew/v1.0.0.rst
index fa1669b1f3343..6b78845b5a305 100644
--- a/doc/source/whatsnew/v1.0.0.rst
+++ b/doc/source/whatsnew/v1.0.0.rst
@@ -324,7 +324,7 @@ Numeric
 - :class:`DataFrame` flex inequality comparisons methods (:meth:`DataFrame.lt`, :meth:`DataFrame.le`, :meth:`DataFrame.gt`, :meth: `DataFrame.ge`) with object-dtype and ``complex`` entries failing to raise ``TypeError`` like their :class:`Series` counterparts (:issue:`28079`)
 - Bug in :class:`DataFrame` logical operations (`&`, `|`, `^`) not matching :class:`Series` behavior by filling NA values (:issue:`28741`)
 - Bug in :meth:`DataFrame.interpolate` where specifying axis by name references variable before it is assigned (:issue:`29142`)
--
+- Bug in :meth:`Series.var` not computing the right value with an integer series with missing values when ddof = 0 (:issue:`29128`)
 
 Conversion
 ^^^^^^^^^^
diff --git a/pandas/core/arrays/integer.py b/pandas/core/arrays/integer.py
index 630c3e50f2c09..1899358bbea62 100644
--- a/pandas/core/arrays/integer.py
+++ b/pandas/core/arrays/integer.py
@@ -652,7 +652,7 @@ def _reduce(self, name, skipna=True, **kwargs):
             data[mask] = self._na_value
 
         op = getattr(nanops, "nan" + name)
-        result = op(data, axis=0, skipna=skipna, mask=mask)
+        result = op(data, axis=0, skipna=skipna, mask=mask, **kwargs)
 
         # if we have a boolean op, don't coerce
         if name in ["any", "all"]:
diff --git a/pandas/tests/arrays/test_integer.py b/pandas/tests/arrays/test_integer.py
index 793de66767cc3..0571299e54cee 100644
--- a/pandas/tests/arrays/test_integer.py
+++ b/pandas/tests/arrays/test_integer.py
@@ -829,6 +829,14 @@ def test_arrow_array(data):
     assert arr.equals(expected)
 
 
+@pytest.mark.parametrize("ddof", [0, 1])
+def test_var_ddof(ddof):
+    s = pd.Series(data=[1, 2, 3, 4, 5, 6, np.nan, np.nan], dtype="Int64")
+    result = s.var(ddof=ddof)
+    expected = np.nanvar([1, 2, 3, 4, 5, 6, np.nan, np.nan], ddof=ddof)
+    assert expected == result
+
+
 # TODO(jreback) - these need testing / are broken
 
 # shift


Code review comments:
diff_hunk: @@ -829,6 +829,14 @@ def test_arrow_array(data):
     assert arr.equals(expected)
 
 
+@pytest.mark.parametrize("ddof", [0, 1])
path: pandas/tests/arrays/test_integer.py
text: @user1:
can you parameterize this over kurt, skew, sem as well

@author:
Done

diff_hunk: @@ -324,7 +324,7 @@ Numeric
 - :class:`DataFrame` flex inequality comparisons methods (:meth:`DataFrame.lt`, :meth:`DataFrame.le`, :meth:`DataFrame.gt`, :meth: `DataFrame.ge`) with object-dtype and ``complex`` entries failing to raise ``TypeError`` like their :class:`Series` counterparts (:issue:`28079`)
 - Bug in :class:`DataFrame` logical operations (`&`, `|`, `^`) not matching :class:`Series` behavior by filling NA values (:issue:`28741`)
 - Bug in :meth:`DataFrame.interpolate` where specifying axis by name references variable before it is assigned (:issue:`29142`)
--
+- Bug in :meth:`Series.var` not computing the right value with an integer series with missing values when ddof = 0 (:issue:`29128`)
path: doc/source/whatsnew/v1.0.0.rst
text: @user1:
say nullable integer dtype

its not ``ddof=0``, rather not passing thru the ``ddof`` arg

@author:
Done