Is there a Faster alternative to ismember function ?

40 views (last 30 days)
Hello everybody,
I have a matirx with big size of row.
and with this I want to re-define the "el" variable using the first column of "nd" variable.
I tried to put this place using the ismember function. But I feels it is quite slow... it took about 3 minutes.
Is there a faster function or a way to replace it?
clear; close all; clc;
% nd has 10 by 5.
nd = [1 0 0 0.36 0; ...
2 0 -0.02 0.33 0; ...
3 0 -0.51 0.33 0; ...
4 0 -0.81 0.33 0; ...
5 0 -0.01 0.33 0; ...
6 0 -0.01 0.33 0; ...
7 0 -0.17 0.33 0; ...
8 0 -0.02 0.33 0; ...
9 0 -0.02 0.33 0; ...
10 0 -0.02 0.33 0];
eld = [1 2; 2 3; 3 4; 4 1; 1 3; 1 2];
% To make "el2" variable, I hope to convert the 1 as 1 0 0 0.36 0 from nd variable. and 2 as 2 0 -0.02 0.33 0.
% I tried using for loop as below. It takes quite long time for the matirx with big size of row.
for i=1:length(eld)
ind1 = find(ismember(nd(:,1),eld(i,1))); % find index to get the data row from nd variable.
ind2 = find(ismember(nd(:,1),eld(i,2)));
% re-define the "el" variable using the first column of "nd" variable.
eld2(i,:) = [nd(ind1,1), nd(ind1,2), nd(ind1,3), nd(ind1,4), nd(ind1,5), ...
nd(ind2,1), nd(ind2,2), nd(ind2,3), nd(ind2,4), nd(ind2,5)];
end

Accepted Answer

Dyuman Joshi
Dyuman Joshi on 3 May 2023
Edited: Dyuman Joshi on 3 May 2023
Generally, using find() and growing variables in a loop tend to cause the code to be slower. Here you can replace find() with logical indexing and use preallocation -
nd = [1 0 0 0.36 0; ...
2 0 -0.02 0.33 0; ...
3 0 -0.51 0.33 0; ...
4 0 -0.81 0.33 0; ...
5 0 -0.01 0.33 0; ...
6 0 -0.01 0.33 0; ...
7 0 -0.17 0.33 0; ...
8 0 -0.02 0.33 0; ...
9 0 -0.02 0.33 0; ...
10 0 -0.02 0.33 0];
eld = [1 2; 2 3; 3 4; 4 1; 1 3; 1 2];
n = size(eld,1);
%preallocation
eld2 = zeros(n,2*size(nd,2));
for i=1:n
%remove find
ind1 = ismember(nd(:,1),eld(i,1)); % find index to get the data row from nd variable.
ind2 = ismember(nd(:,1),eld(i,2));
% re-define the "el" variable using the first column of "nd" variable.
eld2(i,:) = [nd(ind1,1:5) nd(ind2,1:5)]; %combine the terms using indexing
end
eld2
eld2 = 6×10
1.0000 0 0 0.3600 0 2.0000 0 -0.0200 0.3300 0 2.0000 0 -0.0200 0.3300 0 3.0000 0 -0.5100 0.3300 0 3.0000 0 -0.5100 0.3300 0 4.0000 0 -0.8100 0.3300 0 4.0000 0 -0.8100 0.3300 0 1.0000 0 0 0.3600 0 1.0000 0 0 0.3600 0 3.0000 0 -0.5100 0.3300 0 1.0000 0 0 0.3600 0 2.0000 0 -0.0200 0.3300 0
There is another approach as well - Vectorization. As MATLAB is optimized for operation involving matrices and vectors, vectorization leads to faster performance in many cases
[~,n1]=ismember(eld(:,1),nd(:,1));
[~,n2]=ismember(eld(:,2),nd(:,1));
n1=nonzeros(n1);
n2=nonzeros(n2);
eld3 = [eld(n1,1) nd(n1,2:end) eld(n2,2) nd(n2,2:end)]
eld3 = 6×10
1.0000 0 0 0.3600 0 3.0000 0 -0.0200 0.3300 0 2.0000 0 -0.0200 0.3300 0 4.0000 0 -0.5100 0.3300 0 3.0000 0 -0.5100 0.3300 0 1.0000 0 -0.8100 0.3300 0 4.0000 0 -0.8100 0.3300 0 2.0000 0 0 0.3600 0 1.0000 0 0 0.3600 0 4.0000 0 -0.5100 0.3300 0 1.0000 0 0 0.3600 0 3.0000 0 -0.0200 0.3300 0
  2 Comments
Smithy
Smithy on 3 May 2023
Thank you very much for your answer. I really really really appreciate with it. I applied with your another approach and now it took less than 1 sec. Really wonderful.
Dyuman Joshi
Dyuman Joshi on 3 May 2023
That's the power of vectorization!
Glad to have helped :)

Sign in to comment.

More Answers (0)

Tags

Products


Release

R2023a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!