Skip to content

BUG: nanmax/nanmin, 'initial' argument misbehaves #31087

Open

Description

@rgbmrc

Describe the issue:

Even for arrays with valid floats, nanmin/nanmax return nan when initial=nan. Additionally, nan is returned and 'RuntimeWarning: All-NaN axis encountered' is raised whenever an empty slice is encountered, regardless of initial being a valid float or not (in my opinion the warning should not be raised even if initial=nan).

Reproduce the code example:

import numpy as np
np.nanmax([np.nan, 1.0])  # 1.0
np.nanmax([1.0], initial=np.nan)  # np.float64(nan), inconsistent
np.nanmax([], initial=1.0)  # np.float64(nan) & RuntimeWarning: All-NaN axis encountered, omit!
np.nanmin([], initial=np.nan)  # RuntimeWarning: All-NaN axis encountered, omit?

Python and NumPy Versions:

2.3.5
3.14.3 | packaged by conda-forge | (main, Feb 9 2026, 21:56:02) [GCC 14.3.0]

Runtime Environment:

No response

How does this issue affect you or how did you find it:

A use case is obtaining the maximum/minimum of an array, returning nan if it is empty.

Activity

  1. changed the title [-]BUG: nanmax/nanmin do not ignore initial=nan[/-] [+]BUG: nanmax/nanmin, 'initial' argument misbehaves[/+] on Mar 28, 2026
  2. WarrenWeckesser commented on Apr 1, 2026

    @WarrenWeckesser
    Member

    Here's another inconsistency, where the behavior depends on whether the first argument is a Pyhon list or a NumPy array. I expect the first example (pointed out by @rgbmrc in the opening comment) to behave like the second.

    In [12]: np.__version__
    Out[12]: '2.5.0.dev0+git20260330.f91c8a8'
    
    In [13]: np.nanmax([], initial=1.0)
    <ipython-input-13-8564a601b1ff>:1: RuntimeWarning: All-NaN axis encountered
      np.nanmax([], initial=1.0)
    Out[13]: np.float64(nan)
    
    In [14]: np.nanmax(np.array([]), initial=1.0)
    Out[14]: np.float64(1.0)
    
  3. Whatsonyourmind commented on Apr 3, 2026

    @Whatsonyourmind

    The issue is that `nanmax` replaces NaN values with `-inf` (the identity for max) before delegating to the underlying `maximum.reduce`. When `initial=nan` is provided, the replacement logic interacts incorrectly with the `initial` parameter.

    The semantics should be:

    1. Replace all NaN in the data with the identity element (`-inf` for max, `+inf` for min)
    2. Then call `reduce` with the user-provided `initial`

    So `nanmax([nan, 1.0], initial=nan)` should compute `max(-inf, 1.0, initial=nan)`. But since `max(anything, nan) = nan` in IEEE 754, the NaN initial poisons the result.

    For the empty-slice case: `nanmax([], initial=1.0)` replaces NaN (none present), then computes `max(initial=1.0)` over an empty array, which should return 1.0. The warning "All-NaN axis encountered" is incorrect here because the slice isn't all-NaN -- it is empty, and the user explicitly provided a fallback via `initial`.

    The fix should distinguish three cases:

    • Non-empty, has non-NaN: return the actual max (current behavior, works)
    • Non-empty, all-NaN with initial: return `initial` if it is not NaN, else NaN (with warning)
    • Empty with initial: return `initial` unconditionally, no warning

    The `initial` parameter should be treated as a sentinel/fallback value, not as another data point subject to NaN replacement.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions