2
votes

I want to run fast Matlab algorithms over Matrices by ignoring zero-elements.

In the past I just worked with a very slow double-for-loop e.g.

for i = 1 : size(x,1)
   for j = 1 : size(x,2)
        if x(i,j) ~= 0
            ... do something with x(i,j)
        end
     end
end

But how can I make the matrix operation on the whole matrix x? E.g. how can I run

x(i,j) = log(x(i,j)) if x>0 else 0    <-- pseudo code

in Matlab on the whole matrix without for loops?

Finally I want to rewrite lines like

result = sum(sum((V.*log(V./(W*H))) - V + W*H));

with ignoring zeros.

I just need to understand the concept. In case of need I could also use NaN instead of zero, but I didn't find e.g. the function

nanlog()
2
Why are you trying to do this? Calculating likelihoods? - AGS

2 Answers

5
votes

x~=0 returns you the indices of the locations not equal to zero. Then, you can use them to index corresponding locations of x such as follows:

>> x = [1 0 2 3; 0 4 0 5]
x =
     1     0     2     3
     0     4     0     5

>> mean(x(:)) %#mean of all elements
ans =
    1.8750

>> mean(x(x~=0)) %#mean of nonzero elements
ans =
     3

>> x(x~=0) = x(x~=0) + 1
x =
     2     0     3     4
     0     5     0     6
3
votes

You can use NaN as a temporary and make use of the fact that log(NaN) = NaN, like so:

x(x==0) = NaN;
y = log(x);
y(isnan(y)) = 0;

alternatively, you can use logical indexing:

x(x~=0) = log(x(x~=0));

or, if you want to preserve x,

y = x;
y(y~=0) = log(y(y~=0));

For the example you provide, you can just do

result = nansum(nansum((V.*log(V./(W*H))) - V + W*H));

assuming that V == 0 is the problem.