### Translated by

このページのコンテンツは英語から自動翻訳されています。自動翻訳をオフにする場合は「<a class="turn_off_mt" href="#">ここ</a>」をクリックしてください。

## search for elements of a vector in a matrix (without using ismember)

Ashwin Renganathan

### Ashwin Renganathan (view profile)

さんによって質問されました 2017 年 10 月 18 日

### Ashwin Renganathan (view profile)

さんによって 編集されました 2017 年 10 月 20 日
I have a matrix A of size Nx2, N is large. I have another vector b of size nx1 and n<<N. I want to filter out those row indices of A, where both columns could contain any 2 elements of b.
For instance, let
A = [1 2;3 4; 5 6]
b = [1,2,5,6]'
Then output of method(A,b) should be
[1,3]'
(i.e. the first and 3rd rows of A contain 2 elements from b, but not the 2nd row.
I am currently using a combination of ismember and find but seems like ismember is not very efficient because my A, as I said, is very large.
EDIT: (some more background on the problem)
The code has about couple dozen functions of which couple of them call ismember within a loop. The overall code takes several hours to execute when N is in O(1e5) and profiling it showed most of the time is consumed by ismember. The whole point of the question is to verify if (i) ismember is specifically inefficient for large scale code and (ii) are there alternatives that could take only a fraction of ismember 's cputime
EDIT 2: Tried alternative suggestion using 'any'. The cpu time was almost identical.
EDIT 3: Solved. Based on my personal experience, it does seem like ismember is inefficient when used repeatedly used within a large loop. So I replaced it with cellfun (since my 'b' is actually a cell array) & bsxfun and saw 25x speedup. Thanks to everyone that chimed in. I learned a lot!

#### 0 件のコメント

サインイン to comment.

## 4 件の回答

2017 年 10 月 19 日

### Cedric Wannaz (view profile)

2017 年 10 月 19 日

EDIT: I took 3 more minutes and I profiled a small test case (N=1e7, n=1e2). ISMEMBER is more efficient!
Here is an alternative for MATLAB 2016b and above:
>> all( any( A == permute( b, [3,2,1] ), 3 ), 2 )
ans =
3×1 logical array
1
0
1
Then FIND if you need indices.
And here the version for below 2016b:
all( any( bsxfun( @eq, A, permute( b, [3,2,1] )), 3 ), 2 )
If speed maters much, it may be faster to avoid pages:
>> any( A(:,1) == b.', 2 ) & any( A(:,2) == b.', 2 )
ans =
3×1 logical array
1
0
1
but you'll have to profile all solutions and also ISMEMBER, because our guesses about performance are often wrong.

Andrei Bobrov

2017 年 10 月 19 日
+1
Cedric Wannaz

### Cedric Wannaz (view profile)

2017 年 10 月 19 日
Moved here:
There may be ways to pre-process a few things, to eliminate the loop, to parallelize, etc. I built a quick test (with n~10) and you can see that working with an expansion/ANY/etc may be as efficient as Andrei's solution for small values of N, but that as soon as N gets larger ISMEMBER becomes more efficient:

サインイン to comment.

2017 年 10 月 19 日

### Jan (view profile)

2017 年 10 月 19 日

[EDITED Wrong approach:]
You can save some time with calling the internally used C-Mex function:
bs = sort(b); % Omit if b is sorted already!
find(ismembc(A(:,1), bs) & ismembc(A(:,2), bs))
Then b is sorted once only.
Unfortunately ismembc is not documented. It existed at least from Matlab 5.3 to 2016b, but it might be removed from the toolbox in the future.
[EDITED] No, this is slower that ismember. Obviously Matlab uses faster methods now internally.

Andrei Bobrov

### Andrei Bobrov (view profile)

2017 年 10 月 19 日
+1! I love Jan's research.
Jan

### Jan (view profile)

2017 年 10 月 19 日
:-) Thanks, Andrei.
In modern Matlab versions the "ismembc" is replaced by "_ismemberhelper". As other commands starting with an underscore it can be called through builtin also. Then you can omit the error checking and classification of the inputs by:
% b MUST be sorted!
find(builtin('_ismemberhelper', A(:,1), b) & ...
builtin('_ismemberhelper', A(:,2), b));
The speedup with inputs with 1e7 is negligible. This shortcut is only useful, if you process many small problems.
Walter Roberson

### Walter Roberson (view profile)

2017 年 10 月 19 日
I was about to refer to _ismemberhelper, which is what is used by ismember() for some special cases of sorted data. In R2017b look near line 333 of ismember() for a description of _ismemberhelper

サインイン to comment.

### Matt J (view profile)

2017 年 10 月 18 日

find( ismember(A(:,1),b) & ismember(A(:,2),b) )

#### 15 件のコメント

Ashwin Renganathan

### Ashwin Renganathan (view profile)

2017 年 10 月 19 日
n is almost always < 10.
I will see what I can do about sharing the loop. Also the 'any' approach gave similar results.
What I gather from this thread is that (i) I am using the correct methods and (ii) all of them are equally good (or bad). So may be it is an algorithmic issue, that I will have to look into.
Ashwin Renganathan

### Ashwin Renganathan (view profile)

2017 年 10 月 19 日
|Just to be clear, you are not talking to the MathWorks right now. It's a public forum.
I know and I understand. Still this is a MW forum, so I did not want to quote anybody from other public forum.
Ashwin Renganathan

### Ashwin Renganathan (view profile)

2017 年 10 月 19 日
Cedric - I really appreciate it. Thanks! I am re-thinking my algorithm to see scope for improvement. I will try to include the actual loops sometime today if it is still necessary.

サインイン to comment.

2017 年 10 月 19 日

### Andrei Bobrov (view profile)

2017 年 10 月 19 日

all(ismember(A,b),2)
or
diff(A(all(ismember(A,b),2),:),1,2)~=0

#### 0 件のコメント

サインイン to comment.

Translated by