Skip to content

allclose returns True when comparing an empty array to a scalar #5654

Closed

Description

@mrbell

In Numpy v 1.9.1

import numpy as np
np.allclose(np.array([]), 1)

returns True. The value of the scalar doesn't matter. It also returns True when comparing an empty array to an array with only one value, e.g.

np.allclose(np.array([]), np.array([123])

also returns True. It should return False unless comparing two empty arrays if you ask me.

Activity

  1. gmcastil commented on Mar 18, 2015

    @gmcastil
    Contributor

    I'll take a look at this - thanks.

    I should think that np.allclose should return an error of some sort if the lengths of the arrays are not the same. There is certainly nothing in the docstring to suggest the kind of behavior you are seeing. Would a ValueError be the most appropriate if the two arrays are not the same shape?

  2. spencerahill commented on Sep 18, 2017

    @spencerahill
    Contributor

    We have recently bumped into this odd behavior of allclose when shapes don't match. It remains in 1.13:

    In [2]: np.version.version
    Out[2]: '1.13.1'
    
    In [5]: np.allclose(np.ones([5, 1]), np.ones([1]))
    Out[5]: True
    
    In [7]: np.allclose(np.ones([5, 1]), np.ones([5, 2]))
    Out[7]: True
    
    In [8]: np.allclose(np.ones([5, 1]), np.ones([2]))
    Out[8]: True
    
    In [9]: np.allclose(np.ones([5, 1]), np.ones([]))
    Out[9]: True

    In contrast to:

    In [12]: np.allclose(np.ones([5, 1]), np.ones([12, 34]))
    ...
    ValueError: operands could not be broadcast together with shapes (5,1) (12,34)

    Would a ValueError be the most appropriate if the two arrays are not the same shape?

    Yes, I think so.

    Any chance of a fix forthcoming? I'm unfamiliar with numpy's internals, but from the outside it seems like it would be relatively straightforward. If that's the case, I'd be willing to take a stab at it. Thanks!

  3. eric-wieser commented on Sep 18, 2017

    @eric-wieser
    Member

    In the form the problem is stated in the original post, this isn't a bug. Every element of np.array([]) is close to 1.

    You'd expect np.allclose(a, 1) to have the same meaning as np.all(np.isclose(a, 1)). When a == []. then isclose also returns [], and all([]) is defined as `True. So that's why you get the result you do.

    Would a ValueError be the most appropriate if the two arrays are not the same shape?

    What's happening right now is broadcasting. This is useful to check something like if every point in a list of points is close to another point, ie np.allclose(points_2d, point_1d).

    Can you give an argument for why broadcasting isn't desirable here?

  4. spencerahill commented on Sep 18, 2017

    @spencerahill
    Contributor

    As stated in the original post, this isn't a bug

    I was agreeing with the sentiment by @gmcastil that "np.allclose should return an error of some sort if the lengths of the arrays are not the same."

    You'd expect np.allclose(a, 1) to have the same meaning as np.all(np.isclose(a, 1)). When a == []. then isclose also returns [], and all([]) is defined as `True. So that's why you get the result you do.

    Thanks, that is a nice explanation of the logic.

    This is useful to check something like if every point in a list of points is close to another point, ie np.allclose(points_2d, point_1d)

    That's a reasonable use case that I hadn't considered.

    Can you give an argument for why broadcasting isn't desirable here?

    I'll walk back my statement. I see now that the existing behavior is also consistent with that of exact equality:

    >>>np.all(np.equal(np.ones([5, 1]), np.ones([2])))
    True

    There is certainly nothing in the docstring to suggest the kind of behavior you are seeing.

    Adding a note to the docstring may be helpful. The crux of my confusion was that I had incorrectly assumed that these required matching array shapes. Closing this Issue also seems appropriate -- the combination of nothing in the docstring about this and an open Issue on it led me to believe that it was indeed a bug.

    Thanks very much for your help.

  5. eric-wieser commented on Sep 18, 2017

    @eric-wieser
    Member

    Adding a note to the docstring may be helpful.

    I agree - lets leave this open as a reminder to do that

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

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions