3

Although similar questions have been raised a couple of times, still I cannot make a function similar to the matlab ismember function in Python. In particular, I want to use this function in a loop, and compare in each iteration a whole matrix to an element of another matrix. Where the same value is occurring, I want to print 1 and in any other case 0.

Let say that I have the following matrices

d = np.reshape(np.array([ 2.25,  1.25,  1.5 ,  1.  ,  0.  ,  1.25,  1.75,  0.  ,  1.5 ,  0.  ]),(1,10))
d_unique = np.unique(d)

then I have

d_unique
array([ 0.  ,  1.  ,  1.25,  1.5 ,  1.75,  2.25])

Now I want to iterate like

J = np.zeros(np.size(d_unique))
for i in xrange(len(d_unique)):
        J[i] = np.sum(ismember(d,d_unique[i]))

so as to take as an output:

J = [3,1,2,2,1,1]

Does anybody have any idea? Many thanks in advance.

GioR
  • 596
  • 2
  • 8
  • 19
  • 1
    Does the answers to [this question](http://stackoverflow.com/questions/10741346/numpy-frequency-counts-for-unique-values-in-an-array) help? –  Sep 18 '14 at 22:20
  • Also related: http://stackoverflow.com/questions/1273041/how-can-i-implement-matlabs-ismember-command-in-python?rq=1 –  Sep 18 '14 at 22:22
  • 1
    Does this answer your question? [Python equivalent of MATLAB's "ismember" function](https://stackoverflow.com/questions/15864082/python-equivalent-of-matlabs-ismember-function) – Cris Luengo Jun 22 '20 at 00:49
  • @user707650 doesn't help – SteveTz Mar 16 '21 at 11:57

4 Answers4

15

In contrast to other answers, numpy has the built-in numpy.in1d for doing that.

Usage in your case:

bool_array = numpy.in1d(array1, array2)

Note: It also accepts lists as inputs.

EDIT (2021): numpy now recommend using np.isin instead of np.in1d. np.isin preserves the shape of the input array, while np.in1d returns a flattened output.

Yuval Atzmon
  • 5,645
  • 3
  • 41
  • 74
  • 1
    It gives bool not index – Zanam Aug 13 '18 at 19:48
  • 1
    @Zanam, [matlab API](https://www.mathworks.com/help/matlab/ref/ismember.html) also returns Boolean vector for ismember. Moreover, setting `ismember=np.in1d` and executing the code of the question, results with the correct answer. – Yuval Atzmon Sep 22 '18 at 12:12
  • 2
    @YuvalAtzmon the matlab function has a second (optional) output which returns the location, which appears to be of interest to the OP. – goryh Jun 14 '19 at 22:50
2

To answer your question, I guess you could define a ismember similarly to:

def ismember(d, k):
  return [1 if (i == k) else 0 for i in d]

But I am not familiar with numpy, so a little adjustement may be in order.

I guess you could also use Counter from collections:

>>> from collections import Counter
>>> a = [2.25,  1.25,  1.5,  1.,  0.,  1.25,  1.75,  0.,  1.5,  0. ]
>>> Counter(a)
Counter({0.0: 3, 1.25: 2, 1.5: 2, 2.25: 1, 1.0: 1, 1.75: 1})
>>> Counter(a).keys()
[2.25, 1.25, 0.0, 1.0, 1.5, 1.75]
>>> c =Counter(a)
>>> [c[i] for i in sorted(c.keys())]
[3, 1, 2, 2, 1, 1]

Once again, not numpy, you will probably have to do some list(d) somewhere.

fredtantini
  • 15,966
  • 8
  • 49
  • 55
  • Thanks a lot, it works really nice with your second example. The first example is exactly what I was trying to do but at the end I had the following warning : "ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()". I cannot understand what this could mean. – GioR Sep 18 '14 at 22:26
  • @gioR When trying with your code, I have to use `d[0]` and not simply `d` – fredtantini Sep 18 '14 at 22:28
1

Try the following function:

def ismember(A, B):
    return [ np.sum(a == B) for a in A ]

This should very much behave like the corresponding MALTAB function.

Adriaan
  • 17,741
  • 7
  • 42
  • 75
AlexE
  • 334
  • 2
  • 15
  • Oh, it was extremely simple at the end. However, why numpy does not compare the numbers one by one? When I was trying to iterate through the whole matrix I had the following warning: 'ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()' – GioR Sep 18 '14 at 22:28
  • 2
    numpy has a built in function for that, why use list comprehension which is slow? I added an answer below. – Yuval Atzmon Feb 09 '17 at 14:36
0

Try the ismember library from pypi.

pip install ismember

Example:

# Import library
from ismember import ismember

# data
d = [ 2.25,  1.25,  1.5 ,  1.  ,  0.  ,  1.25,  1.75,  0.  ,  1.5 ,  0.  ]
d_unique = [ 0.  ,  1.  ,  1.25,  1.5 ,  1.75,  2.25]

# Lookup
Iloc,idx = ismember(d, d_unique)
 
# Iloc is boolean defining existence of d in d_unique
print(Iloc)
# [[True  True  True  True  True  True  True  True  True  True]]

# indexes of d_unique that exists in d
print(idx)
# array([5, 2, 3, 1, 0, 2, 4, 0, 3, 0], dtype=int64)

print(d_unique[idx])
array([2.25, 1.25, 1.5 , 1.  , 0.  , 1.25, 1.75, 0.  , 1.5 , 0.  ])

print(d[Iloc])
array([2.25, 1.25, 1.5 , 1.  , 0.  , 1.25, 1.75, 0.  , 1.5 , 0.  ])

# These vectors will match
d[Iloc]==d_unique[idx]
erdogant
  • 1,544
  • 14
  • 23