How can I calculate a centered moving average with window size 7?

Hello,
I want to calculate centered moving average of daily values using a 7-day window. That is I want to start with the 4th day being the first center and continue until the 1318 as the last center. And I want the filter to proceed successively from day 4, then 5, then 6, and so on until day 1318 as the center. I have 1321 daily values. I have NaN values in blocks and scattered throughout the data but would like to keep them. I've been given the below code but because I do not know programming, I can not make sense of how I can adapt this to get what I want done. My variable is called Imn_EVI2_d. Thank you for any help.
Daywind=3.5; % window size (days/2, i.e. half of the weekly window width)
Inc=1; %Time step increment (days)
binwid = (Daywind)/1321; %Specifies bin size
start = min(1); %Specifies timestamp when dataset starts Change
last = max(1321); %Specifies timestamp when dataset ends Change
bincenter = start+binwid:(Inc/1321):(last+1); %Specifies center of bin
binnum=length(bincenter); %Specifies how many bins for window size*
Imn_EVI2_d=m;
Imn_EVI2_avgmovall=[]; %Array that moving average will go into. Right now it is empty and 0x0.
Imn_EVI2_d=Imn_EVI2_d(1,:)'; %Change
%This is a for loop that takes the bins above and averages them and takes
%the average and saves it to EVIavgmovall
for i = 1:1:(binnum);
focusday = (1 >= (bincenter(i)-binwid) & (1321 <= (bincenter(i) + binwid)));
EVI_period = Imn_EVI2_d(focusday);
figure(1)
plot(DYear(focusday),Imn_EVI2_d(focusday),'.')
Imn_EVI2_movavg=nanmean(EVI_period);
Imn_EVI2_avgmovall=[Imn_EVI2_avgmovall Imn_EVI2_movavg];
end

 Accepted Answer

d = [nan;2;3;nan;4;5;nan;6;nan;nan];
idx = isnan(d);
d(idx) = 0;
result = conv(d, ones(1,7), 'same') ./ conv(double(idx), ones(1,7), 'same');
Here not all sums over 7 neighboring elements are divided by the window width 7, but by the number of not NaNs.

1 Comment

I see. What does the "double" command do? In the last row of the code, putting ~ before idx does the trick. Currently, it counts the number of NaNs.
Next step: How could I have the standard deviation calculated in the same fashion as the average calculation? Thank you!

Sign in to comment.

More Answers (3)

Assuming each element is the measurement for one day, can't you just do
movingAverage = conv(yourData, ones(1,7), 'same');

6 Comments

It doesn't work. In addition, I have NaN values to deal with.
Please do not claim only, that it does not work, but give us a chance to solve the problem by explaining the details: Do you get an error message (which one?) or do the results differ from your expectations (how?)?
conv() does consider NaNs, but perhaps not in the way you want. So please explain, what you want.
I generated a small test dataset to understand and make things simpler and faster.
d=(1:10).';
d=[nan;2;3;nan;4;5;nan;6;nan;nan];
when I run
movingAverage = conv(d, ones(1,7), 'same');
movingAverage = NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
When I tried with the same dataset without NaNs; I get movingAverage = 10 15 21 28 35 42 49 45 40 34
I tried to explain what I want in the first message in as much detail as I could. I would appreciate if you could help me over the code as well so I understand what is going on. I've spent a long time on it and I think it would be useful for future applications if I can grasp it. Thanks again.
And what is your desired output for the data with nans in it? If we just replaced the nan's with zeros and got the sums, would those be the sums you want? Then if you wanted the means, you could count the non-zeros at each window location and divide by that number to get the means of only those elements that are non nan.
Btw., you need to divide by 7 in addition for a moving average:
conv(yourData, ones(1,7)/7, 'same')
Correct. Your answer does what I was thinking, and (trying to) describe.

Sign in to comment.

Why not use movmean function?

1 Comment

Because when Kemal posted this almost 4 years ago, the movmean() function had not yet been introduced. Now, or actually since R2016a, you can use movmean().

Sign in to comment.

Hi Kemal, did you find solution to your problem ? If so can you share ?

Asked:

on 22 Jan 2013

Answered:

nlm
on 20 Feb 2020

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!