Thanks to visit codestin.com
Credit goes to github.com

Skip to content

BUG: fix ma.diff not preserving mask when using append/prepend #22776

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Jan 18, 2023

Conversation

markopacak
Copy link
Contributor

@markopacak markopacak commented Dec 12, 2022

Closes #22465.

Ported CORE diff to MA

  • Kept only relevant append/prepend code
  • Internally call CORE diff
  • docstring mentions mask preservation + change return type to MaskedArray
  • docstring examples adapted to MA module

Added 2 unit tests

@markopacak markopacak changed the title Bug/ma diff prepend append BUG: fix ma.diff not preserving mask when using append/prepend Dec 12, 2022
@markopacak markopacak marked this pull request as ready for review December 12, 2022 16:54
@seberg
Copy link
Member

seberg commented Dec 20, 2022

Thanks, tests could probably be expanded, but seem OK. The code and examples are very close to the original, so that looks all fine.

The one thing I would like is to not define the method MaskedArray.diff and just make it a function.
We also don't have ndarray.diff (or try to call it from `np.diff) so I don't see a reason to add it here.

@seberg seberg added 01 - Enhancement component: numpy.ma masked arrays 62 - Python API Changes or additions to the Python API. Mailing list should usually be notified. labels Dec 20, 2022
numpy/ma/core.py Outdated
@@ -7341,6 +7341,118 @@ def size(obj, axis=None):
size.__doc__ = np.size.__doc__


def diff(a, n=1, axis=-1, prepend=np._NoValue, append=np._NoValue):
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
def diff(a, n=1, axis=-1, prepend=np._NoValue, append=np._NoValue):
def diff(a, /, n=1, axis=-1, prepend=np._NoValue, append=np._NoValue):

Just thought we should start doing this, its not like a is a name that is nice enough we should promise it in all eternity.

I forgot one other thing (sorry about that): Can you add this function to the stubs file in core.pyi (should be able to adapt the original .pyi file again).

Copy link
Contributor Author

@markopacak markopacak Dec 22, 2022

Choose a reason for hiding this comment

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

I wrote it in the form

def diff(a, /, n=..., axis=..., prepend=..., append=...): ...

like the rest of the file.

Let me know if I should write it like the original:

@overload
def diff(
    a: _T,
    n: L[0],
    axis: SupportsIndex = ...,
    prepend: ArrayLike = ...,
    append: ArrayLike = ...,
) -> _T: ...

Copy link
Member

@seberg seberg left a comment

Choose a reason for hiding this comment

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

Sorry, too late to do a full review now, but wanted to comment on the doc changes.

numpy/ma/core.py Outdated
arrays with length 1 in the direction of axis and the shape
of the input array in along all other axes. Otherwise the
dimension and shape must match `a` except along axis.
.. versionadded:: 1.16.0
Copy link
Member

Choose a reason for hiding this comment

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

Also here newlines... You can remove the .. versionadded:: here, but it actually would be good to add .. versionadded:: 1.25.0 to the top (right before the Parameters section)!

@markopacak markopacak marked this pull request as draft December 25, 2022 18:33
@markopacak markopacak marked this pull request as ready for review December 26, 2022 18:18
@markopacak
Copy link
Contributor Author

@seberg I have made a bit of a mess with accidentally committing some changes and then (kind of) revert (see 2 rev commits). Should I try to rewrite the history?

@charris
Copy link
Member

charris commented Dec 28, 2022

It's fine to rewrite the history of pull requests.

@markopacak markopacak force-pushed the bug/ma-diff-prepend-append branch from 7e86a5c to 95aac56 Compare December 29, 2022 16:44
@markopacak
Copy link
Contributor Author

I don't understand the linux_aarch64 test failing. Can anyone help me out?

@charris
Copy link
Member

charris commented Dec 31, 2022

I don't understand the linux_aarch64 test failing

Network problem, it happens. I reran it.

Copy link
Member

@seberg seberg left a comment

Choose a reason for hiding this comment

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

Thanks, not sure we need the release note, but I guess it doesn't hurt.

@markopacak I am happy to put this in soon, because I think it looks correct.

Looking at the original code now, if n == 0 it returns a unmodified, but here we do not have that code branch. To be clear, the original code looks buggy here when prepend/append is used (I also don't like that a is returned directly rather than a copy in all other cases, but so be it...)

A test that it fails if a is 0-dimensional would also not be bad (I am sure it must fail in the concatenation, which was explicit in the np.diff code).

@markopacak
Copy link
Contributor Author

markopacak commented Jan 8, 2023

@seberg Update: added check for a.ndim == 0 and for for n == 0 (just like in np.diff).

Note: I just realized that if I pass a non-MA array without prepend/append to MA diff, I get back a non-MA array, despite my docstring saying that a MaskedArray is always returned (I even added an example in the docstrings):

>>> u8_arr = np.array([1, 0], dtype=np.uint8)  # base np array
>>> np.ma.diff(u8_arr)  # MA diff
array([255], dtype=uint8)  # <-- base array returned, not a MaskedArray

Should I convert any input a to a MaskedArray (by using np.ma.asanyarray, the base diff does something similar)? The line would be placed right before if n == 0: ...

Or should I just add a note to the docs?

@charris
Copy link
Member

charris commented Jan 17, 2023

@seberg Ping.

if n < 0:
raise ValueError("order must be non-negative but got " + repr(n))

if a.ndim == 0:
Copy link
Member

Choose a reason for hiding this comment

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

Sorry for not looking earlier. I am happy to do this to keep it identical to the original code (will open an issue about it, I don't think n == 0 is correct, it should check for prepend/append to be None).

Doing a.ndim == 0 may fail on e.g. list inputs when it currently didn't fail, so we probably also need that np.ma.asanyarray() call first that the old function has.

Copy link
Contributor Author

@markopacak markopacak Jan 18, 2023

Choose a reason for hiding this comment

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

Added np.ma.asanyarray to keep it identical to BASE diff.

Pls ping me when you open that issue, I'd also like to take a look.

@seberg
Copy link
Member

seberg commented Jan 18, 2023

Thanks, lets put it in, sorry it took a bit! CircleCI is failing because the PR was opened a bit ago and its now still on Python 3.8 here. It was working before and the docs weren't changed, so going to take that chance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
01 - Enhancement 62 - Python API Changes or additions to the Python API. Mailing list should usually be notified. component: numpy.ma masked arrays
Projects
Development

Successfully merging this pull request may close these issues.

BUG: Numpy ma diff skipping the mask when using argument 'prepend'
3 participants