I want to get the set difference of arrays of tuples. For instance, for
import numpy as np
a = np.empty((2,), dtype=object)
a[0] = (0, 1)
a[1] = (2, 3)
b = np.empty((1,), dtype=object)
b[0] = (2, 3)
I would like to have a function, say set_diff, such that set_diff(a, b) = array([(0, 1)], dtype=object). The function np.setdiff1d doesn't work, np.setdiff1d(a, b) yields array([(0, 1), (2, 3)], dtype=object).
Is there a function that does the job or a way to make np.setdiff1d have the desired behavior ?
Why not use Python sets?
In [339]: a = [(0,1),(2,3)]; b = [(2,3)]
In [340]: set(a).difference(b)
Out[340]: {(0, 1)}
Object dtype arrays don't gain much, if any thing, over lists.
numpy is primarily a numeric array package. Object dtype arrays are something of an after-thought, and are more list like. Math on objects is hit-of-miss, and things like this that involve sorting and equality tests often don't work, or work in unpredictable ways. Don't give up on regular Python types like list, tuples and sets just because someone told you numpy is faster!
The problem you're facing is actually documented in a number of Stack Overflow posts. It turns out that this specific function, np.setdiff1d, does not operate on arrays of tuples, and seemingly any objects aside scalars. This post provides a simple demonstration, and this one gives some more details on the issue.
Both posts have good fixes for related problems. In case of your code, if computationally permissible, I would move back to Python sets and lists:
import numpy as np
a = np.empty((3,), dtype=object)
a[0] = (0, 1)
a[1] = (2, 3)
a[2] = (0, 3)
b = np.empty((2,), dtype=object)
b[0] = (2, 3)
b[1] = (3, 4)
set_a = set(a)
set_b = set(b)
output = np.array(list(set_a-set_b))
print(set_a)
print(set_b)
print(output)
Here the code ends up turning the set difference back to Numpy array, but of course that is optional. Also, I extended your example a little, to demonstrate the dimensions of the final array, and more importantly, the fact that it only contains the elements of a that are not in b, and not vice versa.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With