Home > utilities > runmean.m

runmean

PURPOSE ^

RUNMEAN - Very fast running mean (aka moving average) filter

SYNOPSIS ^

function Y = runmean(X, m, dim, modestr) ;

DESCRIPTION ^

 RUNMEAN - Very fast running mean (aka moving average) filter
   For vectors, Y = RUNMEAN(X,M) computes a running mean (also known as
   moving average) on the elements of the vector X. It uses a window of
   2*M+1 datapoints. M an positive integer defining (half) the size of the
   window. In pseudo code: 
     Y(i) = sum(X(j)) / (2*M+1), for j = (i-M):(i+M), and i=1:length(X) 

   For matrices, Y = RUNMEAN(X,M) or RUNMEAN(X,M,[]) operates on the first   
   non-singleton dimension of X. RUNMEAN(X,M,DIM) computes the running
   mean along the dimension DIM.

   If the total window size (2*M+1) is larger than the size in dimension
   DIM, the overall average along dimension DIM is computed.

   As always with filtering, the values of Y can be inaccurate at the
   edges. RUNMEAN(..., MODESTR) determines how the edges are treated. MODESTR can be
   one of the following strings:
     'edge'    : X is padded with first and last values along dimension
                 DIM (default)
     'zero'    : X is padded with zeros
     'mean'    : X is padded with the mean along dimension DIM 

   X should not contains NaNs, yielding an all NaN result. NaNs can be
   replaced by using, e.g., "inpaint_nans" created by John D'Errico.

   Examples
     runmean([1:5],1) 
       % ->  1.33  2  3  4 4.67
     runmean([1:5],1,'mean') 
       % ->  2 2 3 4 4
     runmean([2:2:10],1,1) % dimension 1 is larger than 2*(M=1)+1 ...
       % -> 2 4 6 8 10
     runmean(ones(10,7),3,2,'zero') ; % along columns, using mode 'zero'
     runmean(repmat([1 2 4 8 NaN 5 6],5,1),2,2) ; 
       % -> all NaN result
     A = rand(10,10) ; A(2,7) = NaN ;
     runmean(A,3,2) ; 
       % -> column 7 is all NaN
     runmean(1:2:10,100) % mean
       % -> 5 5 5 5 5

   This is an incredibly fast implementation of a running mean, since
   execution time does not depend on the size of the window.

   See also MEAN, FILTER

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function Y = runmean(X, m, dim, modestr) ;
0002 % RUNMEAN - Very fast running mean (aka moving average) filter
0003 %   For vectors, Y = RUNMEAN(X,M) computes a running mean (also known as
0004 %   moving average) on the elements of the vector X. It uses a window of
0005 %   2*M+1 datapoints. M an positive integer defining (half) the size of the
0006 %   window. In pseudo code:
0007 %     Y(i) = sum(X(j)) / (2*M+1), for j = (i-M):(i+M), and i=1:length(X)
0008 %
0009 %   For matrices, Y = RUNMEAN(X,M) or RUNMEAN(X,M,[]) operates on the first
0010 %   non-singleton dimension of X. RUNMEAN(X,M,DIM) computes the running
0011 %   mean along the dimension DIM.
0012 %
0013 %   If the total window size (2*M+1) is larger than the size in dimension
0014 %   DIM, the overall average along dimension DIM is computed.
0015 %
0016 %   As always with filtering, the values of Y can be inaccurate at the
0017 %   edges. RUNMEAN(..., MODESTR) determines how the edges are treated. MODESTR can be
0018 %   one of the following strings:
0019 %     'edge'    : X is padded with first and last values along dimension
0020 %                 DIM (default)
0021 %     'zero'    : X is padded with zeros
0022 %     'mean'    : X is padded with the mean along dimension DIM
0023 %
0024 %   X should not contains NaNs, yielding an all NaN result. NaNs can be
0025 %   replaced by using, e.g., "inpaint_nans" created by John D'Errico.
0026 %
0027 %   Examples
0028 %     runmean([1:5],1)
0029 %       % ->  1.33  2  3  4 4.67
0030 %     runmean([1:5],1,'mean')
0031 %       % ->  2 2 3 4 4
0032 %     runmean([2:2:10],1,1) % dimension 1 is larger than 2*(M=1)+1 ...
0033 %       % -> 2 4 6 8 10
0034 %     runmean(ones(10,7),3,2,'zero') ; % along columns, using mode 'zero'
0035 %     runmean(repmat([1 2 4 8 NaN 5 6],5,1),2,2) ;
0036 %       % -> all NaN result
0037 %     A = rand(10,10) ; A(2,7) = NaN ;
0038 %     runmean(A,3,2) ;
0039 %       % -> column 7 is all NaN
0040 %     runmean(1:2:10,100) % mean
0041 %       % -> 5 5 5 5 5
0042 %
0043 %   This is an incredibly fast implementation of a running mean, since
0044 %   execution time does not depend on the size of the window.
0045 %
0046 %   See also MEAN, FILTER
0047 
0048 % for Matlab R13
0049 % version 3.0 (sep 2006)
0050 % Jos van der Geest
0051 % email: jos@jasen.nl
0052 
0053 % History:
0054 %   1.0 (2003) created, after a snippet from Peter Acklam (?)
0055 %   1.1 (feb 2006) made suitable for the File Exchange (extended help and
0056 %       documentation)
0057 %   1.2 (feb 2006) added a warning when the window size is too big
0058 %   1.3 (feb 2006) improved help section
0059 %   2.0 (sep 2006) working across a dimension of a matrix.
0060 %   3.0 (sep 2006) several treatments of the edges.
0061 
0062 % Acknowledgements: (sep 2006) Thanks to Markus Hahn for the idea of
0063 % working in multi-dimensions and the way to treat edges.
0064 
0065 error(nargchk(2,4,nargin)) ;
0066 
0067 if ~isnumeric(m) || (numel(m) ~= 1) || (m < 0) || fix(m) ~= m,
0068     error('The window size (M) should be a positive integer') ;
0069 end
0070 
0071 if nargin == 2,
0072     dim = [] ;
0073     modestr = 'edge' ;
0074 elseif nargin==3,
0075     if ischar(dim),
0076         % no dimension given
0077         modestr = dim ;
0078         dim = [] ;
0079     else 
0080         modestr = 'edge' ;
0081     end
0082 end
0083 
0084 modestr = lower(modestr) ;
0085 
0086 % check mode specifier
0087 if ~ismember(modestr,{'edge','zero','mean'}),
0088     error('Unknown mode') ;
0089 end
0090 
0091 szX = size(X) ;
0092 if isempty(dim),
0093     dim = min(find(szX>1)) ;
0094 end
0095 
0096 if m == 0 || dim > ndims(X),
0097     % easy
0098     Y = X ;
0099 else
0100     mm = 2*m+1 ;
0101     if mm >= szX(dim),
0102         % if the window is larger than X, average all
0103         sz2 = ones(size(szX)) ; 
0104         sz2(dim) = szX(dim) ;
0105         Y = repmat(mean(X,dim),sz2) ;
0106     else
0107         % here starts the real stuff
0108         % shift dimensions so that the desired dimensions comes first
0109         [X, nshifts] = shiftdim(X, dim-1); 
0110         szX = size(X) ;
0111         % make the rest of the dimensions columns, so we have a 2D matrix
0112         % (suggested of Markus Hahn)
0113         X = reshape(X,szX(1),[]) ; 
0114         % select how to pad the matrix
0115         switch (modestr),
0116             case 'edge'
0117                 % pad with first and last elements
0118                 Xfirst = repmat(X(1,:),m,1) ;
0119                 Xlast = repmat(X(end,:),m,1) ;
0120             case 'zero'
0121                 % pad with zeros
0122                 Xfirst = zeros(m,1) ;
0123                 Xlast= zeros(m,1) ;
0124             case 'mean',
0125                 % pad with the average
0126                 Xfirst = repmat(mean(X,1),m,1) ;
0127                 Xlast = Xfirst ;
0128         end        
0129         % pad the array
0130         Y = [zeros(1,size(X,2)) ; Xfirst ; X ; Xlast] ;       
0131         % the cumsum trick (by Peter Acklam ?)
0132         Y = cumsum(Y,1) ;
0133         Y = (Y(mm+1:end,:)-Y(1:end-mm,:)) ./ mm ;
0134         
0135         % reshape into original size
0136         Y = reshape(Y,szX)   ;
0137         % and re-shift the dimensions
0138         Y = shiftdim(Y,ndims(Y)-nshifts) ;
0139     end
0140 end
0141 
0142 % =====================
0143 %  CODE OF VERSION 1.3
0144 % =====================
0145 
0146 % function Y = runmean(X,m) ;
0147 % % RUNMEAN - Very fast running mean filter for vectors
0148 % %   Y = RUNMEAN(X,M) computes a running mean on vector X using a window of
0149 % %   2*M+1 datapoints. X is a vector, and M an positive integer defining
0150 % %   (half) the size of the window. In pseudo code:
0151 % %     Y(i) = sum(X(j)) / (2*M+1), for j = (i-M):(i+M), and i=1:length(X)
0152 % %
0153 % %   If the total window size (2M+1) is larger than the length of the vector, the overall
0154 % %   average is returned.
0155 % %
0156 % %   Example:
0157 % %     runmean(1:10,1) % ->
0158 % %     [1.3333 2 3 4 5 6 7 8 9 9.6667]
0159 % %
0160 % %   This is an incredibly fast implementation of a running average, since
0161 % %   execution time does not depend on the size of the window.
0162 % %
0163 % %   X should not contains NaNs (a NaN will result in a all NaN result)
0164 % %   At both ends the values of Y can be inaccurate, as the first and last
0165 % %   values of X are used multiple times.
0166 % %
0167 % %   See also MEAN
0168 %
0169 % % for Matlab R13
0170 % % version 1.3 (feb 2006)
0171 % % Jos van der Geest
0172 % % email: jos@jasen.nl
0173 %
0174 % % History:
0175 % % 1.0 (2003) created, after a snippet from Peter Acklam (?)
0176 % % 1.1 (feb 2006) made suitable for the File Exchange (extended help and
0177 % % documentation)
0178 % % 1.2 (feb 2006) added a warning when the window size is too big
0179 % % 1.3 (feb 2006) improved help section
0180 %
0181 % error(nargchk(2,2,nargin)) ;
0182 %
0183 % sz = size(X) ;
0184 %
0185 % if numel(sz) ~= 2 || (min(sz) ~= 1),
0186 %     error('X should be a vector') ;
0187 % end
0188 %
0189 % if any(isnan(X)),
0190 %     error('NaNs cannot be dealt with') ;
0191 % end
0192 %
0193 % if ~isnumeric(m) || (numel(m) ~= 1) || (m < 0) || fix(m) ~= m,
0194 %     error('The window size (M) should be a positive integer') ;
0195 % elseif m == 0,
0196 %     Y = X ;
0197 %     return ;
0198 % end
0199 %
0200 % mm = 2*m+1 ;
0201 %
0202 % if mm >= prod(sz),
0203 %     % if the window is larger than X, average all
0204 %     warning('Window size is larger than the length of the vector.')
0205 %     Y = repmat(mean(X),sz) ;
0206 % else
0207 %     % the cumsum trick ...
0208 %     Y = [repmat(X(1),m,1) ; X(:) ; repmat(X(end),m,1)] ;
0209 %     Y = [0 ; cumsum(Y)] ;
0210 %     Y = (Y(mm+1:end)-Y(1:end-mm)) / mm ;
0211 %     Y = reshape(Y,sz) ;
0212 % end
0213

Generated on Wed 20-Feb-2019 16:06:01 by m2html © 2005