MATLAB Answers

0

How can I average the first 14 columns, the second 14 columns, and so on and so forth?

Asked by Natasha D on 28 Feb 2019
Latest activity Commented on by Natasha D on 4 Mar 2019
I have a matrix that is 533x54527 (rows x columns). I want to write a loop that takes the first 14 columns and averages across the columns. Then saves the new average into a new array. Then, I want to average the next 14 columns and append the new values into the initial new array (without using the 'append' command - it's not included in my toolbox).
How can I script it so that the last remaining columns (maybe 5 or 10) are also averaged (since 14 does not go into 54527 evenly)?
Thank you!

  2 Comments

I'm confused about one thing.
The first array of data to process will by 533x14. And you say you want the average across rows. My understanding of that phrase is that the result would be a 1x14 array.
But I'm guessing you actually want the average across columns, resulting in a 533x1 array for that step.
Can you please clarify?
Yes, you are correct - apologies for the confusion! Average across the columns, resulting in a 533x1 array.

Sign in to comment.

3 Answers

Answer by Geoff Hayes
on 28 Feb 2019
 Accepted Answer

Natasha - so if you were to do this by hand, you would do something like
iteration column start column end
========= ============ ==========
1 1 14
2 15 28
3 29 42
etc.
So the column start increments by 14 each time. This will be the step size in a for loop. You could then check on each iteration to see if you have 14 columns to average...if not, then just use what is remaining.
Presumably, when you average across the rows, you will take the 533x14 matrix and reduce this to a 533x1 column. This means that you will - once all averages concatenated - have a 533xN matrix. To determine N you could do
N = floor(54527/14);
% if not evenly divisible by 14, then we need to add an extra column
if mod(54527,14) ~= 0
N = N + 1;
end
averageData = zeros(533, N);
We pre-allocate memory to averageData so that we can just update it on each iteration of the loop (rather than concatenating or appending the data).
Your code might then look like
stepSize = 14;
numColumns = 54527;
N = floor(numColumns/stepSize);
% if not evenly divisible by 14, then we need to add an extra column
if mod(numColumns,stepSize) ~= 0
N = N + 1;
end
averageData = zeros(533, N);
n = 1;
for k = 1:stepSize:numColumns
averageData(:, n) = mean(myData(:, k:min(k + stepSize - 1, numColumns)), 2);
n = n + 1;
end
We use min(k + 14 - 1, 54527) to determine the last column in our set to average and this handles the case where there are less than 14 columns remaining.

  0 Comments

Sign in to comment.


Answer by the cyclist
on 28 Feb 2019

Assuming you actually want to average over columns (see my question above), I believe
out = movmean(M,[0 13],2);
out = out(:,1:14:end);
does what you want.
I didn't carefully check the result, so I may not have the indexing quite right, but you can definitely do what you want with the movmean command.

  1 Comment

Sign in to comment.


Answer by Jan
on 28 Feb 2019
Edited by Jan
on 28 Feb 2019

Reshape the data to blocks of the wanted width and calculate the average by mean or sum(X)/Width. Then append the mean over the trailing part on demand:
X = rand(533, 54527);
W = 14;
[S1, S2] = size(X);
Right = mod(S2, W);
Main = S2 - Right;
XX = reshape(X(:, 1:Main), S1, W, Main / W);
Y = reshape(sum(XX, 2) / W, S1, Main / W);
if Right ~= 0
Y = [Y, sum(X(:, Main + 1:S2), 2) / Right];
end

  0 Comments

Sign in to comment.