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

### Natasha D (view profile)

on 28 Feb 2019
Latest activity Commented on by Natasha D

on 4 Mar 2019

### Geoff Hayes (view profile)

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!

the cyclist

### the cyclist (view profile)

on 28 Feb 2019
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.
Natasha D

### Natasha D (view profile)

on 28 Feb 2019
Yes, you are correct - apologies for the confusion! Average across the columns, resulting in a 533x1 array.

R2017b

### Geoff Hayes (view profile)

on 28 Feb 2019

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.

### the cyclist (view profile)

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.

Natasha D

### Natasha D (view profile)

on 4 Mar 2019
This also works! Thanks!

on 28 Feb 2019
Edited by Jan

### Jan (view profile)

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