MOVING_AVERAGE Smooths a vector through the moving average method. Syntax: [Y,Nsum] = moving_average(X,F,DIM); Input: X - Vector or matrix of finite elements. F - Window semi-length. A positive scalar (default 0). DIM - If DIM=1: smooths the columns (default); elseif DIM=2 the rows. Output: Y - Smoothed X elements. Nsum - Number of not NaN's elements that fixed on the moving window. Provided to get a sum instead of a mean: Y.*Nsum. Description: Quickly smooths the vector X by averaging each element along with the 2*F elements at its sides. The elements at the ends are also averaged but the extrems are left intact. With the windows size defined in this way, the filter has zero phase. Example: x = 2*pi*linspace(-1,1)'; yn = cos(x) + 0.25 - 0.5*rand(size(x)); ys = moving_average(yn,4); plot(x,[yn ys]), legend('noisy','smooth',4), axis tight See also FILTER, RECTWIN and MOVING_AVERAGE2, NANMOVING_AVERAGE, NANMOVING_AVERAGE2 by Carlos Vargas and RUNMEAN by Jos van der Geest.
0001 function [Y,Nsum] = moving_average(X,F,DIM) 0002 %MOVING_AVERAGE Smooths a vector through the moving average method. 0003 % 0004 % Syntax: 0005 % [Y,Nsum] = moving_average(X,F,DIM); 0006 % 0007 % Input: 0008 % X - Vector or matrix of finite elements. 0009 % F - Window semi-length. A positive scalar (default 0). 0010 % DIM - If DIM=1: smooths the columns (default); elseif DIM=2 the rows. 0011 % 0012 % Output: 0013 % Y - Smoothed X elements. 0014 % Nsum - Number of not NaN's elements that fixed on the moving window. 0015 % Provided to get a sum instead of a mean: Y.*Nsum. 0016 % 0017 % Description: 0018 % Quickly smooths the vector X by averaging each element along with the 0019 % 2*F elements at its sides. The elements at the ends are also averaged 0020 % but the extrems are left intact. With the windows size defined in 0021 % this way, the filter has zero phase. 0022 % 0023 % Example: 0024 % x = 2*pi*linspace(-1,1)'; 0025 % yn = cos(x) + 0.25 - 0.5*rand(size(x)); 0026 % ys = moving_average(yn,4); 0027 % plot(x,[yn ys]), legend('noisy','smooth',4), axis tight 0028 % 0029 % See also FILTER, RECTWIN and MOVING_AVERAGE2, NANMOVING_AVERAGE, 0030 % NANMOVING_AVERAGE2 by Carlos Vargas and RUNMEAN by Jos van der Geest. 0031 0032 % Copyright 2006-2008 Carlos Vargas, nubeobscura@hotmail.com 0033 % $Revision: 3.1 $ $Date: 2008/03/12 18:20:00 $ 0034 0035 % Written by 0036 % M. in S. Carlos Adrián Vargas Aguilera 0037 % Physical Oceanography PhD candidate 0038 % CICESE 0039 % Mexico, march 2008 0040 % 0041 % nubeobscura@hotmail.com 0042 % 0043 % Download from: 0044 % http://www.mathworks.com/matlabcentral/fileexchange/loadAuthor.do?objec 0045 % tType=author&objectId=1093874 0046 0047 % 2008 Mar. Use CUMSUM as RUNMEAN by Jos van der Geest, no more 0048 % subfunctions. 0049 0050 %% Error checking: 0051 if ~nargin 0052 error('Moving_average:Inputs','There are no inputs.') 0053 elseif nargin<2 || isempty(F) 0054 F = 0; 0055 end 0056 if F==0 0057 Y = X; 0058 return 0059 end 0060 F = round(F); 0061 ndim = ndims(X); 0062 if (ndim ~= 2) 0063 error('Moving_average:Inputs','Input is not a vector or matrix.') 0064 end 0065 [N,M] = size(X); 0066 if nargin<3 || isempty(DIM) 0067 DIM = 1; 0068 if N == 1 0069 DIM = 2; 0070 end 0071 end 0072 if DIM == 2 0073 X = X.'; 0074 [N,M] = size(X); 0075 end 0076 if 2*F+1>N 0077 warning('Moving_average:Inputs',... % bug fixed 06 Mar 2008 0078 'Window size must be less or equal as the number of elements.') 0079 Y = X; 0080 if DIM == 2 0081 Y = Y.'; 0082 end 0083 return 0084 end 0085 0086 %% Window width 0087 Wwidth = 2*F + 1; 0088 0089 %% Smooth the edges but with the first and last element intact 0090 F2 = Wwidth - 2; 0091 Nsumedge = repmat((1:2:F2)',1,M); 0092 Y1 = X( 1:F2,:); 0093 Y2 = flipud(X(N-F2+1:N ,:)); 0094 Y1 = cumsum(Y1,1); 0095 Y2 = cumsum(Y2,1); 0096 Y1 = Y1(1:2:F2,:)./Nsumedge; 0097 Y2 = Y2(1:2:F2,:)./Nsumedge; 0098 0099 %% Recursive moving average method 0100 % With CUMSUM trick copied from RUNMEAN by Jos van der Geest (12 mar 2008) 0101 Y = [zeros(F+1,M); X; zeros(F,M)]; 0102 Y = cumsum(Y,1); 0103 Y = Y(Wwidth+1:end,:)-Y(1:end-Wwidth,:); 0104 Y = Y/Wwidth; 0105 0106 %% Sets the smoothed edges: 0107 Y( 1:F,:) = Y1; 0108 Y(N-F+1:N,:) = flipud(Y2); 0109 0110 %% Get the number of elements that were averaged for each element: 0111 if nargout == 2 0112 Nsum = repmat(Wwidth,size(Y)); 0113 Nsum( 1:F,:) = Nsumedge; 0114 Nsum(N-F+1:N,:) = flipud(Nsumedge); 0115 if DIM ==2 0116 Nsum = Nsum.'; 0117 end 0118 end 0119 0120 %% Return the correct size: 0121 if DIM == 2 0122 Y = Y.'; 0123 end 0124 0125 %% % Recursive moving average code before Jos trick: 0126 % Y = X; 0127 % Y(F+1,:) = sum(X(1:Wwidth,:),1); 0128 % for n = F+2:N-F 0129 % Y(n,:) = sum([Y(n-1,:); X(n+F,:); -X(n-F-1,:)],1); 0130 % end 0131 % Y = Y/Wwidth;