2

Let us say I have two nested structures of the following kind:

[(array, (array, array, array)), (array, (array, array, array))]

All of the interesting data inside are NumPy arrays. What is the easiest way to compare two of such data structures? I could index and compare each of the corresponding arrays individually, but that is a lot of indexing and typing.

If there is an easy way to just "swallow" all of the numbers in the contained arrays and "serialise" them unambiguously into one NumPy array, that resulting array would be easy to compare. I am mainly interesting in checking if two such arrays are equal (== or np.allclose()). I have naïvely tried doing so by throwing a np.array around the whole thing but that only converts the outermost list to a NumPy array.

4
  • It is always a list of tuple of size 2 with first element an array and second element a tuple of arrays? Commented Jul 27, 2015 at 20:32
  • @Holt Yes, always that tuple structure but in fact, the list may contain more of them. Commented Jul 28, 2015 at 6:31
  • @mgilson I may want to accept tiny numerical differences - hence allclose. Commented Jul 28, 2015 at 6:31
  • @mgilson actually a == b gives me "ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()" Commented Oct 14, 2021 at 21:58

2 Answers 2

1

To work with np.allclose, you'll need your own comparison function.

def compare(a, b):
    if isinstance(a, (list, tuple)) and isinstance(b, type(a)):
        for aa, bb in zip(a, b):
            if not compare(aa, bb):
                return False  # Short circuit
        return True
    else:  # numpy arrays
        return numpy.allclose(a, b)

Of course, you could get more fancy (passing kwargs down from compare to allclose for example) and your input checking could be more robust, but this should give you the general idea ...

Sign up to request clarification or add additional context in comments.

3 Comments

If the 2 lists have the same numeric values, but different array objects, that == produces a truth value error. == tests between arrays can produce a a boolean array. The allclose approach should be safer.
@hpaulj -- derp. Thanks. (you can tell I haven't been working with numpy a lot lately). I'll remove the first bit then.
Clever. I notice that and isinstance(b, type(a)) also ensures that one is actually checking two objects of the same type and since this works to some extent as input validation, it's a bit unfortunate that this also triggers the numpy.allclose comparison when that fails. I am adding a variation of your answer hoping to fix this.
1

This is a slight modification of https://stackoverflow.com/a/31662874/865169 to try to filter out the situation where a and b are not of the same type, i.e. are not comparable in the sense we are trying to check here:

def compare(a, b):
    if not isinstance(b, type(a)):
        raise TypeError('The two input objects must be of same type')
    else:
        if isinstance(a, (list, tuple)):
            for aa, bb in zip(a, b):
                if not compare(aa, bb):
                    return False  # Short circuit
            return True
        else:  # numpy arrays
            return np.allclose(a, b)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.