Reputation: 3
I am using Matlab and I have a problem with filtering a matrix. The matrix is filled with rising numbers, I want to delete all entries in the matrix which are closer then a given intervall to the entry before (n-1).
I did this already with a for loop, and it worked. The problem is, it took five hours to compute!
my code:
for i=2:y
if ((arrMaster1(i-1)+deadtime)<arrMaster1(i))
j=j+1;
arrMaster1cut(j,3)=int64(arrMaster1(i));
else
end
end
Upvotes: 0
Views: 38
Reputation: 30047
Firstly, you can do all of your subtractions at once, rather than individual elements each loop. This can be made even easier by using diff
like so
diffs = diff(arrMaster1(1:y));
% equivalent to: diffs = arrMaster1(2:y) - arrMaster1(1:y-1);
Then create a logical array, to test if your differences are greater than deadtime
:
keepthese = [true, diffs > deadtime];
% outputs vector like [1 0 1 1 1 0 ...], of length y, where 1 is true and 0 is false
% diffs is of length y-1, so extra "true" is needed.
% There is a "true" in the place of every element you want to keep.
Finally, create your output:
arrMaster1cut = int64(arrMaster1(keepthese));
% This is called logical indexing, you're choosing all elements of
% arrMaster1 where keepthese has the value 1 / true
All together:
diffs = diff(arrMaster1(1:y)); % Get differences for tolerencing
keepthese = [true, diffs > deadtime]; % Get indices to keep
arrMaster1cut = int64(arrMaster1(keepthese)); % Create output
Edit note
The keepthese
vector is a row vector, hence concatenation with a comma. If arrMaster1
is a column vector, then diffs
will be too, so instead use a semicolon
keepthese = [true; diffs > deadtime]; % Get indices to keep (column vector)
A note on indexing
Logical indexing vs normal indexing. Let's say we wanted to pull the 1st, 2nd and 4th elements from a 5 element matrix. We could use two methods:
elements = mymatrix([1,2,4]);
elements = mymatrix(logical([1,1,0,1,0])); % logical converts 1/0 to true/false
Obviously, the second approach (logical indexing) isn't as clear in this example. However, when used above it allows us to avoid a call to the find
function, which would convert the logical index into a numbered vector:
find([1,1,0,1,0]); % = [1,2,4]
Therefore, we gain a speed advantage.
Upvotes: 1
Reputation: 4195
i don't have all your code so this is just a guess, but your code maybe run so slow because you don't pre-allocate memory for arrMaster1cut
, and you change it's size in each iteration.
moreover, you can vectorize the entire code using diff
:
% random arrMaster1 array
y = 100;
arrMaster1 = randi(100,[1 y]);
deadtime = 5;
% differences vector
d = diff(arrMaster1);
% differences greater than deadtime
idxs = find(d > deadtime);
% produce arrMaster1cut
arrMaster1cut1 = int64(arrMaster1(idxs+1));
% your method
j = 0;
arrMaster1cut2 = [];
for i=2:y
if ((arrMaster1(i-1)+deadtime)<arrMaster1(i))
j=j+1;
arrMaster1cut2(j)=int64(arrMaster1(i));
else
end
end
% check for equal results
isequal(arrMaster1cut2, arrMaster1cut1)
Upvotes: 0