Skip to content

Add ddof argument to np.nanvar and np.nanstd (fixes #6611)#10540

Open
furperson wants to merge 9 commits into
numba:mainfrom
furperson:fix-nanstd-nanvar-ddof-v2
Open

Add ddof argument to np.nanvar and np.nanstd (fixes #6611)#10540
furperson wants to merge 9 commits into
numba:mainfrom
furperson:fix-nanstd-nanvar-ddof-v2

Conversation

@furperson
Copy link
Copy Markdown

Fixes #6611

Added ddof (Delta Degrees of Freedom) parameter to np.nanvar and
np.nanstd in nopython mode, matching NumPy behaviour.

Changes:

  • np.nanvar(a, ddof=0) : default ddof=0 preserves backward compatibility
  • np.nanstd(a, ddof=0) : passes ddof through to nanvar
  • Fixed ZeroDivisionError when all elements are NaN (now returns nan,
    consistent with NumPy)
  • Fixed complex dtype handling: uses abs(v - m)**2 instead of (v - m)**2
    to return a real result, consistent with NumPy

Tests added in numba/tests/test_array_reductions.py:

  • test_nanvar_ddof
  • test_nanstd_ddof

@furperson furperson marked this pull request as ready for review April 16, 2026 18:11
@furperson
Copy link
Copy Markdown
Author

Hi, could someone please take a look at this when you get a chance? All CI checks are passing. Thanks!

@furperson
Copy link
Copy Markdown
Author

Hi @swap357 , could you please take a look at this PR when you have a moment? All CI checks are passing. Thanks!

Copy link
Copy Markdown
Contributor

@swap357 swap357 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the PR, @furperson! Did a first pass review and left comments. Since this is changing overload signature, could you document points about added support and limitations for np.nanvar and np.nanstd on - https://numba.readthedocs.io/en/stable/extending/overloading-guide.html.

Comment thread numba/np/arraymath.py

@overload(np.nanvar)
def np_nanvar(a):
def np_nanvar(a, axis=None, dtype=None, out=None, ddof=0):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The standard practice in Numba is to keep signature minimal. If the scope of the PR is ddof, can we keep signature to only that ? errors for the other args can handled by dispatcher -

    With argument(s): '(array(float64, 1d, C), axis=int64)':
   Rejected as the implementation raised a specific error:
     TypingError: got an unexpected keyword argument 'axis'

Comment thread numba/np/arraymath.py

@overload(np.nanstd)
def np_nanstd(a):
def np_nanstd(a, axis=None, dtype=None, out=None, ddof=0):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above, keep only needed changes to signature

Comment thread numba/np/arraymath.py Outdated
def nanvar_impl(a, axis=None, dtype=None, out=None, ddof=0):
# For complex input NumPy uses abs(v - m)**2 (always real)
m = np.nanmean(a)
n = 0
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please try and keep the existing implementation and naming for variables, if it's not modifying logic. It helps to understand what's changing. Synthetic refactor can be a separate PR if needed.

def test_nanvar_ddof(self):
self.check_reduction_basic(array_nanvar_ddof0, prec='double')
self.check_reduction_basic(array_nanvar_ddof1, prec='double')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Complex branch not being tested

@furperson
Copy link
Copy Markdown
Author

Hi @swap357, I've updated the signature to minimal (a, ddof=0) as requested, but test_signatures_match_overloaded_api is now failing on Windows (py313_np23). The checker compares against numpy's full signature (a, axis=None, dtype=None, out=None, ddof=0, keepdims=<no value>, ...) and doesn't stop at * on Windows as it does on Linux.

Previously the full signature (a, axis=None, dtype=None, out=None, ddof=0) passed this test. Could you advise on the recommended approach here - should I keep the full signature up to ddof, or is there another way to handle this?

@swap357
Copy link
Copy Markdown
Contributor

swap357 commented May 13, 2026

Hi @swap357, I've updated the signature to minimal (a, ddof=0) as requested, but test_signatures_match_overloaded_api is now failing on Windows (py313_np23). The checker compares against numpy's full signature (a, axis=None, dtype=None, out=None, ddof=0, keepdims=<no value>, ...) and doesn't stop at * on Windows as it does on Linux.

Previously the full signature (a, axis=None, dtype=None, out=None, ddof=0) passed this test. Could you advise on the recommended approach here - should I keep the full signature up to ddof, or is there another way to handle this?

Hi @furperson, Thank you for the changes. Apologies, but I now think my earlier review comment wasn't entirely correct. I went through the testing code and codebase to check for overloads with less params than their corresponding numpy signature. I did find some, like np.cov here -

def np_cov(m, y=None, rowvar=True, bias=False, ddof=None):

It escapes the test because it does mention supported args upto ddof and omits the rest of the unsupported ones after it (fweights, aweights)
For this PR, I think it would be correct to revert to what you had and write all args upto ddof.

For the unsupported ones, guarding it with error is good. There is precedent at np.average for that as well -

numba/numba/np/arraymath.py

Lines 1037 to 1039 in 3c9c807

if axis is not None and not isinstance(axis, types.NoneType):
def np_average_impl(a, axis=None, weights=None):
raise TypeError("Numba does not support average with axis.")

Again, thank you for the patience!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature Request: Support ddof argument in np.nan[std | var]

2 participants