# moving_average

## PURPOSE

MOVING_AVERAGE Smooths a vector through the moving average method.

## SYNOPSIS

function [Y,Nsum] = moving_average(X,F,DIM)

## DESCRIPTION

    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.

## CROSS-REFERENCE INFORMATION

This function calls:

This function is called by:

- moving_average2 MOVING_AVERAGE2 Smooths a matrix through the moving average method.
- nanmoving_average2 NANMOVING_AVERAGE2 Smooths a matrix through the moving average method.

## SOURCE CODE

    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;