Skip to content

np.diff is broken for boolean ndarrays in 1.13.0 #9251

Description

@soupault

Should modify the docstring accordingly, raise a meaningful error, or (preferably) make it work by hidding some logic under the hood.

Traceback:

In [11]: x = np.array([[True, True], [False, False]])

In [12]: np.diff(x)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-12-59225436601c> in <module>()
----> 1 np.diff(x)

/usr/lib/python3.6/site-packages/numpy/lib/function_base.py in diff(a, n, axis)
   1924         return diff(a[slice1]-a[slice2], n-1, axis=axis)
   1925     else:
-> 1926         return a[slice1]-a[slice2]
   1927 
   1928 

TypeError: numpy boolean subtract, the `-` operator, is deprecated, use the bitwise_xor, the `^` operator, or the logical_xor function instead.

In [13]: np.__version__
Out[13]: '1.13.0'

xref scikit-image/scikit-image#2681

Activity

  1. jaimefrio commented on Jun 14, 2017

    @jaimefrio
    Member

    This seems like an easy fix. The diff function is pure Python and lives here:

    https://github.com/numpy/numpy/blob/master/numpy/lib/function_base.py#L1835

    You would probably want to branch on a.dtype == bool, and given the note regarding booleans in the docstring, use ^ (or !=) instead of - to keep backwards compatibility.

  2. eric-wieser commented on Jun 14, 2017

    @eric-wieser
    Member

    It seems to me that if - is deprecated, then diff is perfectly reasonable to disallow too.

  3. matthew-brett commented on Jun 14, 2017

    @matthew-brett
    Contributor

    Well - I can see the purity argument for disallowing, but it seems to me that it is reasonable to expect diff to work on booleans, and not surprising that scikit image was doing that. So I would have thought a branch on bool was the better route.

  4. soupault commented on Jun 14, 2017

    @soupault
    ContributorAuthor

    I'd vote for keeping the functionality. If we all agree, I'll submit a patch later today or tomorrow.

    P.S. Could you, please, point me at the discussion where the rationale for deprecating -= was given?

  5. jaimefrio commented on Jun 14, 2017

    @jaimefrio
    Member

    If diff is deprecated on booleans, then the docstring needs updating to reflect that. And we'd probably still want to branch on bool to raise a more in context error?

  6. eric-wieser commented on Jun 14, 2017

    @eric-wieser
    Member

    Seems to me that we might want an np.uint1 type that behaves as a integer and not a boolean, on which np.diff and - can be defined.

  7. matthew-brett commented on Jun 14, 2017

    @matthew-brett
    Contributor

    My vote would be to avoid the user having to stop and debug an error on np.diff(some_bools); first - it breaks backward compatibility, and second, the desired behavior is useful and clearly defined.

  8. eric-wieser commented on Jun 14, 2017

    @eric-wieser
    Member

    first - it breaks backward compatibility, and second, the desired behavior is useful and clearly defined.

    Both of these arguments apply to np.subtract too, don't they? Perhaps that discussion should be revisited

  9. matthew-brett commented on Jun 14, 2017

    @matthew-brett
    Contributor

    Yes, they do, and if you think of instinctively think of diff as implementing subtract then you'd probably want an error. My belief is that people think of diff in a slightly different way from subtract, so that they would agree that subtracting bools does not make sense, whereas taking a diff of bools does - meaning 'is this value different from the previous one'.

  10. eric-wieser commented on Jun 14, 2017

    @eric-wieser
    Member

    "is this value different from the previous one" sounds like an operation worthy of it's own name that generalizes to all dtypes, rather than spelling it np.diff(x).astype(bool).

    Perhaps ufunc.pairwise(x, axis=...), implemented as ufunc(x[:-1], x[1:]) ignoring the axis argument? That would make the desired function np.not_equal.pairwise.

    Although pairwise might imply the behaviour that outer already has...

  11. matthew-brett commented on Jun 14, 2017

    @matthew-brett
    Contributor

    Sure, that might be a good idea as well - but I would still argue that it would be kinder (practicality beats purity) to forgive this way of thinking of bools and np.diff.

  12. added this to the 1.13.1 release milestone on Jun 14, 2017
  13. 5 remaining items

  14. jaimefrio commented on Jun 14, 2017

    @jaimefrio
    Member

    One other thing we should do is add a test for diff using a boolean array, be it to assert_raises or to validate the result.

    Since the solution seems to be controversial (I think I'm with Matthew on this one, although I don't care much either way), I have sent an e-mail to the list so that everyone gets a say.

  15. mhvk commented on Jun 14, 2017

    @mhvk
    Contributor

    I'm also of the practical beats purity type here, especially since this used to work. Somehow, like @matthew-brett, there is a "diff" is "difference/differs" confusion in my mind, and I certainly have used np.diff as a quick way to find places where values changed.

    p.s. @jaimefrio - I didn't see any message on the (numpy discussion) mailing list.

  16. rgommers commented on Jun 14, 2017

    @rgommers
    Member

    +1 for practicality.

    And definitely -1 for a new function. If it's useful, then put it in diff. The namespace is way too large already.

  17. jaimefrio commented on Jun 15, 2017

    @jaimefrio
    Member

    Yes, I noticed I couldn't find my mail in the archives to link it here. But there's an email in my sent folder to [email protected] at 18:00 CET. Perhaps the server is acting up again? Or were those issues fixed for good already?

  18. charris commented on Jun 15, 2017

    @charris
    Member

    Wrong address, it has moved ;) [email protected] .

  19. jaimefrio commented on Jun 15, 2017

    @jaimefrio
    Member

    Ah, that would explain it...

    Here's a link to the mail, resent to the correct address, for future reference:

    https://mail.python.org/pipermail/numpy-discussion/2017-June/076877.html

  20. soupault commented on Jun 15, 2017

    @soupault
    ContributorAuthor

    This doesn't look good at all - scipy/scipy#7493 .

  21. charris commented on Jun 16, 2017

    @charris
    Member

    Someone want to make a PR adding support for boolean arrays to diff?

  22. soupault commented on Jun 16, 2017

    @soupault
    ContributorAuthor

    @charris I do. Are we all agreed on this?

  23. charris commented on Jun 16, 2017

    @charris
    Member

    @soupault I think that is the consensus.

  24. eric-wieser commented on Jul 13, 2017

    @eric-wieser
    Member

    This also applies to np.gradient. Do we fix that too? (could fold into #9411)

  25. soupault commented on Feb 21, 2018

    @soupault
    ContributorAuthor

    Kind ping on @eric-wieser 's question. Should we fix np.gradient as well?

  26. mhvk commented on Feb 26, 2018

    @mhvk
    Contributor

    Personally, I don't see much point in supporting gradients of bool arrays.

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions