diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst index 5160d2ea8b8fe..5c53267158eab 100644 --- a/doc/source/whatsnew/v3.0.0.rst +++ b/doc/source/whatsnew/v3.0.0.rst @@ -716,6 +716,7 @@ Numeric - Bug in :meth:`DataFrame.cov` raises a ``TypeError`` instead of returning potentially incorrect results or other errors (:issue:`53115`) - Bug in :meth:`DataFrame.quantile` where the column type was not preserved when ``numeric_only=True`` with a list-like ``q`` produced an empty result (:issue:`59035`) - Bug in :meth:`Series.dot` returning ``object`` dtype for :class:`ArrowDtype` and nullable-dtype data (:issue:`61375`) +- Bug in :meth:`Series.std` and :meth:`Series.var` when using complex-valued data (:issue:`61645`) - Bug in ``np.matmul`` with :class:`Index` inputs raising a ``TypeError`` (:issue:`57079`) Conversion diff --git a/pandas/core/nanops.py b/pandas/core/nanops.py index 25fb6e6181082..666b108717837 100644 --- a/pandas/core/nanops.py +++ b/pandas/core/nanops.py @@ -1014,7 +1014,11 @@ def nanvar( avg = _ensure_numeric(values.sum(axis=axis, dtype=np.float64)) / count if axis is not None: avg = np.expand_dims(avg, axis) - sqr = _ensure_numeric((avg - values) ** 2) + if values.dtype.kind == "c": + # Need to use absolute value for complex numbers. + sqr = _ensure_numeric(abs(avg - values) ** 2) + else: + sqr = _ensure_numeric((avg - values) ** 2) if mask is not None: np.putmask(sqr, mask, 0) result = sqr.sum(axis=axis, dtype=np.float64) / d diff --git a/pandas/tests/reductions/test_reductions.py b/pandas/tests/reductions/test_reductions.py index a7bb80727206e..485b50f65736e 100644 --- a/pandas/tests/reductions/test_reductions.py +++ b/pandas/tests/reductions/test_reductions.py @@ -780,6 +780,12 @@ def test_var_masked_array(self, ddof, exp): assert result == result_numpy_dtype assert result == exp + def test_var_complex_array(self): + # GH#61645 + ser = Series([-1j, 0j, 1j], dtype=complex) + assert ser.var(ddof=1) == 1.0 + assert ser.std(ddof=1) == 1.0 + @pytest.mark.parametrize("dtype", ("m8[ns]", "M8[ns]", "M8[ns, UTC]")) def test_empty_timeseries_reductions_return_nat(self, dtype, skipna): # covers GH#11245