Skip to content

Inconsistent behaviour with mean on masked array with and without dimensions given. #3841

Description

@damskii9992

The mean gives different results depending on how it is taken on a multi-dimensional masked array. The following is a code-snippet that showcases it:

array = sc.DataArray(
    sc.array(dims=['x', 'y'], values=[[1.0, 1.0, 1.0, 1.0], [0.0, np.inf, 0.0, 1.0]]),
    masks={'mask' : sc.array(dims=['x', 'y'], values=[[False, False, False, False], [False, True, False, False]])}
    )
array.mean() # gives 0.714286, (5/7) as it should
array.mean(dim=['x', 'y']) # gives 0.75
array.mean(dim=['y', 'x'] # gives 0.66667

Activity

  1. nvaytet commented on Feb 11, 2026

    @nvaytet
    Member

    I guess this is because when we say .mean(['x', 'y']), we do first mean along 'x', and then mean along 'y'.
    If you follow this reasoning, then you can understand where the results come from.

    You get the same results from numpy:

    import numpy as np
    
    a = np.ma.masked_array(data=[[1.0, 1.0, 1.0, 1.0], [0.0, np.inf, 0.0, 1.0]],
                       mask=[[False, False, False, False], [False, True, False, False]])
    
    a.mean()  # np.float64(0.7142857142857143)
    a.mean(axis=0).mean(axis=0)  # np.float64(0.75)
    a.mean(axis=1).mean(axis=0)  # np.float64(0.6666666666666666)

    However, numpy differs with us when you pass both axes in one go:

    a.mean(axis=(0, 1))  # np.float64(0.7142857142857143)
    a.mean(axis=(1, 0))  # np.float64(0.7142857142857143)

    which I guess is the desired behaviour?

    So we should detect if the list of dims passed comprises all dims, and then just return the .mean() instead of doing the dims one by one?

  2. jl-wynen commented on Feb 12, 2026

    @jl-wynen
    Member

    So we should detect if the list of dims passed comprises all dims, and then just return the .mean() instead of doing the dims one by one?

    That wouldn't be enough. E.g., given a 3d array and passing 2 dims, we would still differ from numpy.

  3. damskii9992 commented on Feb 12, 2026

    @damskii9992
    Author

    That wouldn't be enough. E.g., given a 3d array and passing 2 dims, we would still differ from numpy.

    And that is exactly my use-case. I'd like the mean to work like .mean() on each value of the third dimension. So something like:

    for i in array.dims['t']:
       new_array['t', i] = array['t',i].mean()
  4. nvaytet commented on Feb 17, 2026

    @nvaytet
    Member

    Should the mean operation then just be implemented as the sum divided by volume, instead of doing mean on one dimension at a time?

  5. damskii9992 commented on Feb 17, 2026

    @damskii9992
    Author

    Should the mean operation then just be implemented as the sum divided by volume, instead of doing mean on one dimension at a time?

    I am not sure what exactly you mean by volume, but if volume is the number of elements that were summed up, then yeah, that's the behavior I would expect :)

  6. self-assigned this
    on Mar 12, 2026
  7. added theissue type on May 18, 2026
  8. damskii9992 commented on Jun 3, 2026

    @damskii9992
    Author

    Any updates on this issue?

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions