Reputation: 78790
I am asking myself what the most "vectorized" solution for finding the values of the first non-zero column of a matrix would look like. If a vectorized solution exists but is very ugly/hackish, I am also asking for the most elegant solution.
Let's say we have a Matrix M
, for which we can assume that it contains at least one non-zero value:
M =
0 0 1 0 0
0 0 2 0 0
0 0 3 0 42
0 0 4 0 0
0 0 0 0 0
and I would like to find the values in the first column which is not all zeros; so for this example the desired output would be:
column =
1
2
3
4
0
My first attempt employed a for
loop and is working alright, but it is probably not making full use of the tools available in matlab.
>> for i = 1:size(M,2)
col = M(:,i);
if find(col) % empty array evaluates to false
break;
end
end
>> col
col =
1
2
3
4
0
Another solution I came up with makes use of nested find
and cellfun
calls, but it's probably still not the best approach to the problem.
>> C = find(cellfun(@isempty, cellfun(@find, num2cell(M,1), 'UniformOutput', 0)) == 0)
C =
3 5
>> M(:,C(1))
ans =
1
2
3
4
0
Upvotes: 3
Views: 584
Reputation: 381
As you asked for a 'vectorised' solution, this one should run a little faster due to logical indexing:
tic; M(:,sum(M)>0); toc
Elapsed time is 0.000020 seconds.
tic; M(:,find(any(M),1)); toc
Elapsed time is 0.000028 seconds.
(Although this is not the most accurate way to measure execute time)
A more accurate way is to measure with timeit
on a bigger matrix:
M=rand(1024);
f1= @() M(:,sum(M)>0);
f2= @() M(:,find(any(M),1));
t1=timeit(f1)
t2=timeit(f2)
t1 =
0.0070
t2 =
2.3288e-05
Upvotes: 2
Reputation: 221754
Here's a way to do it and I would leave it to you for measuring the performance improvements from it (if you are interested of course) -
M(:,find(any(M),1))
I would suggest looking into Logical Operation in MATLAB
and logical indexing
, as they come in real handy for indexing purposes. These should serve you well.
Upvotes: 4