0
votes

I have a 64 X 64 matrix that I need to find the column-wise mean values for.

However, instead of dividing by the total number of elements in each column (i.e. 64), I need to divide by the total number of non-zeros in the matrix.

I managed to get it to work for a single column as shown below. For reference, the function that generates my matrix is titled fmu2(i,j).

q = 0;
for i = 1:64
    if fmu2(i,1) ~= 0;
        q = q + 1;
    end
end

for i = 1:64
    mv = (1/q).*sum(fmu2(i,1));
end

This works for generating the "mean" value of the first column. However, I'm having trouble looping this procedure so that I will get the mean for each column. I tried doing a nested for loop, but it just calculated the mean for the entire 64 X 64 matrix instead of one column at a time. Here's what I tried:

q = 0;
for i = 1:64
    for j = 1:64
        if fmu2(i,j) ~= 0;
            q = q +1;
        end
    end
end

for i = 1:64
    for j = 1:64
        mv = (1/q).*sum(fmu2(i,j));
    end
end

Like I said, this just gave me one value for the entire matrix instead of 64 individual "means" for each column. Any help would be appreciated.

2

2 Answers

2
votes

For one thing, do not call the function that generates your matrix in each iteration of a loop. This is extremely inefficient and will cause major problems if your function is complex enough to have side effects. Store the return value in a variable once, and refer to that variable from then on.

Secondly, you do not need any loops here at all. The total number of nonzeros is given by the nnz function (short for number of non-zeros). The sum function accepts an optional dimension argument, so you can just tell it to sum along the columns instead of along the rows or the whole matrix.

m = fmu2(i,1)
averages = sum(m, 1) / nnz(m)

averages will be a 64-element array with an average for each column, since sum(m, 1) is a 64 element sum along each column and nnz(m) is a scalar.

One of the great things about MATLAB is that it provides vectorized implementations of just about everything. If you do it right, you should almost never have to use an explicit loop to do any mathematical operations at all.

2
votes

If you want the column-wise mean of non-zero elements you can do the following

m = randi([0,5], 5, 5); % some data
avg = sum(m,1) ./ sum(m~=0,1);

This is a column-wise sum of values, divided by the column-wise number of elements not equal to 0. The result is a row vector where each element is the average of the corresponding column in m.

Note this is very flexible, you could use any condition in place of ~=0.