# public numpy /numpy

### Subversion checkout URL

You can clone with HTTPS or Subversion.

# ENH: make array_equal+array_equiv work for record arrays/structured arrays#146

Closed
wants to merge 2 commits into from
 +45 5

### 3 participants

Implementation of http://projects.scipy.org/numpy/ticket/1941 with tests. Please comment if the behaviour of array_equiv in commit 4b896f8 or in HEAD is preferred.

 Derek Homeier `ENH: enable comparison of structured arrays with array_equal|equiv` `4b896f8` Derek Homeier `Extended the definition of array_equiv to different field names` ```Modified array_equiv to consider structured arrays with differently named fields, but equivalent data, to be equivalent.``` `c036bce`
Collaborator
commented on `c036bce`

I'd much prefer for the names to match exactly, matching the way NumPy already does struct array comparison:

``````>>> x = np.array([(0,1),(2,3)], dtype=[('a', 'i4'), ('b', 'i4')])
>>> y = np.array([(0,1),(2,3)], dtype=[('a', 'i4'), ('b', 'i4')])
>>> x == y
array([ True,  True], dtype=bool)
>>> y = np.array([(0,1),(2,4)], dtype=[('a', 'i4'), ('b', 'i4')])
>>> x == y
array([ True, False], dtype=bool)
>>> y = np.array([(0,1),(2,3)], dtype=[('a', 'i4'), ('c', 'i4')])
>>> x == y
False
``````

That would make the difference between array_equal and array_equiv - but structure array comparison seems to behave similar to both, so maybe it's really a matter of taste:

```>>> x = np.array([(0,1),(2,3)], dtype=[('a', 'i4'), ('b', 'i4')])
>>> y = np.array([(0,1),(2,3)], dtype=[('a', 'i4'), ('b', 'i4')]).reshape(1,-1)
>>> x == y
array([[ True,  True]], dtype=bool)
```

I was not aware that '==' did work already, so maybe most of the array_equal code could simply be replaced by

```return bool((a1 == a2).all())
```

?

Collaborator

I actually fixed the == in 1.6. It had already been implemented, but incorrectly. I think even just

``````return (a1 == a2).all()
``````

should be fine, but it's worth having tests which confirm this. One thing to think about for the future, is that I think == for struct dtypes should return a struct dtype with matching names but all 'bool' dtypes, and all() should be extended to reduce the bool-struct to a single value as well... The above line of code would still work correctly with these changes, so that's good.

referenced this pull request in thouis/numpy-trac-migration Open

### Issue #3489: ENH: array_equal / array_equiv for structured arrays (migrated from Trac #1941)

referenced this pull request in thouis/numpy-trac-migration Open

### Issue #5739: ENH: array_equal / array_equiv for structured arrays (Trac #1941)

referenced this pull request Closed

### Issue #745: ValueError or segfault wrapping ALLOCATABLE f90 arrays using ifort on AMD64/EM64T (Trac #147)

referenced this pull request Closed

### Issue #2534: ENH: array_equal / array_equiv for structured arrays (Trac #1941)

Owner
commented

@dhomeier How does this story end?

referenced this pull request Merged

### Pull Request #3322: Fix array_equal and array_equiv issue

Owner
commented

Closed by #3322.

closed this
to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 2 unique commits by 1 author.

Aug 26, 2011
`ENH: enable comparison of structured arrays with array_equal|equiv` `4b896f8`
`Extended the definition of array_equiv to different field names`
```Modified array_equiv to consider structured arrays with differently
named fields, but equivalent data, to be equivalent.```
`c036bce`
This page is out of date. Refresh to see the latest.

Showing 2 changed files with 45 additions and 5 deletions.

1. numpy/core/numeric.py
2. numpy/core/tests/test_numeric.py
25  numpy/core/numeric.py
 `@@ -1924,7 +1924,8 @@ def allclose(a, b, rtol=1.e-5, atol=1.e-8):` 1924 1924 ` ` 1925 1925 ` def array_equal(a1, a2):` 1926 1926 ` """` 1927 `- True if two arrays have the same shape and elements, False otherwise.` 1927 `+ True if two arrays have the same shape and elements, including field` 1928 `+ names (dtype.names) for structured arrays. False otherwise.` 1928 1929 ` ` 1929 1930 ` Parameters` 1930 1931 ` ----------` `@@ -1961,7 +1962,15 @@ def array_equal(a1, a2):` 1961 1962 ` return False` 1962 1963 ` if a1.shape != a2.shape:` 1963 1964 ` return False` 1964 `- return bool(logical_and.reduce(equal(a1,a2).ravel()))` 1965 `+ # test for structured arrays` 1966 `+ if a1.dtype.names:` 1967 `+ if a1.dtype != a2.dtype:` 1968 `+ return False` 1969 `+ return bool( all([ logical_and.reduce(equal(a1[n],a2[n]).ravel())` 1970 `+ for n in a1.dtype.names ]) )` 1971 `+ else:` 1972 `+ return bool(logical_and.reduce(equal(a1,a2).ravel()))` 1973 `+` 1965 1974 ` ` 1966 1975 ` def array_equiv(a1, a2):` 1967 1976 ` """` `@@ -1969,6 +1978,8 @@ def array_equiv(a1, a2):` 1969 1978 ` ` 1970 1979 ` Shape consistent means they are either the same shape, or one input array` 1971 1980 ` can be broadcasted to create the same shape as the other one.` 1981 `+ Fields of structured arrays are considered consistent if all fields are` 1982 `+ consistent (in order of dtype), even if they are differently named.` 1972 1983 ` ` 1973 1984 ` Parameters` 1974 1985 ` ----------` `@@ -2002,8 +2013,16 @@ def array_equiv(a1, a2):` 2002 2013 ` a1, a2 = asarray(a1), asarray(a2)` 2003 2014 ` except:` 2004 2015 ` return False` 2016 `+ # for structured arrays try to compare all fields,` 2017 `+ # even if they have different names` 2005 2018 ` try:` 2006 `- return bool(logical_and.reduce(equal(a1,a2).ravel()))` 2019 `+ if a1.dtype.names:` 2020 `+ if len(a1.dtype.names) != len(a2.dtype.names):` 2021 `+ return False` 2022 `+ return bool( all([logical_and.reduce(equal(a1[n],a2[m]).ravel())` 2023 `+ for n,m in zip(a1.dtype.names,a2.dtype.names)]) )` 2024 `+ else:` 2025 `+ return bool(logical_and.reduce(equal(a1,a2).ravel()))` 2007 2026 ` except ValueError:` 2008 2027 ` return False` 2009 2028 ` `
25  numpy/core/tests/test_numeric.py
 `@@ -640,7 +640,15 @@ def test_array_equal(self):` 640 640 ` res = array_equal(array([1,2]), array([1,3]))` 641 641 ` assert_(not res)` 642 642 ` assert_(type(res) is bool)` 643 `-` 643 `+ res = array_equal(array((1,2), dtype=[('i','i4'),('v','f8')]),` 644 `+ array((1,2), dtype=[('i','i4'),('v','f8')]))` 645 `+ assert_(res)` 646 `+ assert_(type(res) is bool)` 647 `+ res = array_equal(array((1,2), dtype=[('i','i4'),('v','f8')]),` 648 `+ array((1,2), dtype=[('n','i4'),('f','f8')]))` 649 `+ assert_(not res)` 650 `+ assert_(type(res) is bool)` 651 `+ ` 644 652 ` def test_array_equiv(self):` 645 653 ` res = array_equiv(array([1,2]), array([1,2]))` 646 654 ` assert_(res)` `@@ -670,7 +678,20 @@ def test_array_equiv(self):` 670 678 ` res = array_equiv(array([1,2]), array([[1,2,3],[4,5,6],[7,8,9]]))` 671 679 ` assert_(not res)` 672 680 ` assert_(type(res) is bool)` 673 `-` 681 `+ res = array_equiv(array((1,2), dtype=[('i','i4'),('v','f8')]),` 682 `+ array((1,2), dtype=[('i','i4'),('v','f8')]))` 683 `+ assert_(res)` 684 `+ assert_(type(res) is bool)` 685 `+ res = array_equiv(array([(1,2),(3,4)],` 686 `+ dtype=[('i','i4'),('v','f8')]),` 687 `+ array([(1,2),(3,4)],` 688 `+ dtype=[('i','i4'),('v','f8')]).reshape((1,-1)))` 689 `+ assert_(res)` 690 `+ assert_(type(res) is bool)` 691 `+ res = array_equiv(array((1,2), dtype=[('i','i4'),('v','f8')]),` 692 `+ array((1,2), dtype=[('n','i4'),('f','f8')]))` 693 `+ assert_(res)` 694 `+ assert_(type(res) is bool)` 674 695 ` ` 675 696 ` def assert_array_strict_equal(x, y):` 676 697 ` assert_array_equal(x, y)`

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.