LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

MOVING AVERAGE

Hi all,
 
Did anybody knows a function, or a fast way, to do a moving average from the first to the last point, of an array of data.
 
Maybe there is a function in the Advanced Analysis library to do it, but I have not found it.
 
Many thanks.
 
 
Image Hosted by ImageShack.us
0 Kudos
Message 1 of 11
(7,096 Views)
I have never found such a function in the NI library, I've had to write code to create a window that I slide across the data set, calculating the average.  Are you trying to smooth data?

Menchar
0 Kudos
Message 2 of 11
(7,096 Views)
Yes, I'm trying to smooth the data aquired, I have done some tests with lowpass filters, but the best results are with this kind of average done with an analysis software, and now I want to implement it in my app.
Image Hosted by ImageShack.us
0 Kudos
Message 3 of 11
(7,094 Views)
The basic moving average or "boxcar" filter is pretty trivial to code:

for(output=0, i=0; i<size; i++)
    output+=data[i];
output\=size;

You can be more efficient and use pointers to the first and last data and modify the sum by subtracting the oldest data, adding in the newest and repeating the division for each sample point as it comes in.  With modern cpus this is more trouble than its worth -- I've real-time Linux code that does 240 interrupts/sec and the ISR does three or four MA filters on different data channels with time constants from 1/10 sec to 1 sec and never had the need for more complicated code, now back the days of the Z80.... 🙂

--wally.


   
Message 4 of 11
(7,088 Views)

Here's a running average of doubles, with discard of outliers.  It is not efficient.

 

/*==========================================================================*/
/* Function: RunningAverage                                                */
/* Purpose : Computes 10-point running average of input data array       */
/*      : stores average into old array locations, overwriting raw data  */
/* Inputs  : int nMaxIndex  max number of data values in the input array  */
/*         : double rawData pointer to the raw data array to be smoothed    */
/*         : double MIN_DATA_VALUE valid data value low limit          */
/*         : double MAX_DATA_VALUE valid data value high limit           */
/* Outputs : none                                         */
/* Return  : none                                           */
/*==========================================================================*/

void RunningAverage (int nMaxIndex, double rawData[], double MIN_DATA_VALUE, double MAX_DATA_VALUE)  {

 int i;
 int j;
 int nValidReadings;
 double fSmoothArray[4200];
 
 // -------------------------------------------------------------------
 // smooth raw data with a 5-second running mean
 // This is numerically inefficient code, because it sums the same values
 // many times.  No need for efficiency here, we're in-between segments...
 // -------------------------------------------------------------------
 
 // compute a 10-point running average (there are two data points per second)
 
 for (i = 10; i < nMaxIndex; i++) {
  fSmoothArray[i] = 0.0;
  nValidReadings = 0;
  
  for (j = i - 10; j < i; j++) {
   // Disregard 'spurious' data points
   if ((rawData[j] > MIN_DATA_VALUE) && (rawData[j] < MAX_DATA_VALUE)) {
    fSmoothArray[i] += rawData[j];
    nValidReadings++;
   }
  }
  
  if (nValidReadings > 0) {
   fSmoothArray[i] = fSmoothArray[i] / nValidReadings;
  }
  else {
   fSmoothArray[i] = INVALID_DATA_VALUE;
  }
 }
 
 for (i = 10; i < nMaxIndex; i++) {
  rawData[i] = fSmoothArray[i];
 }
 
 return;
 
}  // end, RunningAverage

Message 5 of 11
(7,083 Views)
The kind of average I mean is as follows
 
ex:
Signal[ ] = Array of n points
averaging = 3
 
averaged_signal[i] = Signal[i-3] + Signal[i-2] + Signal[i-1]+ Signal[i] + Signal[i+1]+ Signal[i+2]+ Signal[i+3] / ((averaging*2)+1)
 
I know is not difficult to implement this in a function, but is a very common average method so it surprise me a lot there is not a specific function to do it.
 
Many thanks menchar and wally for your help
 
 
 
P.D. menchar I have not seen your second post. Many thanks


Mensaje editado por xavi
Image Hosted by ImageShack.us
0 Kudos
Message 6 of 11
(7,078 Views)
xavi,

Try the Mean() function from the Advanced Analysis Library:

Prototype:

AnalysisLibErrType Mean (const double Input_Array[], int Number_of_Elements, double *Mean);

Colin.

Message 7 of 11
(7,061 Views)
Init your array to zeros and simply modify my for loop:

for(output=0, i=-size; i<=size; i++)
    output+=buf[i];
output/=(2size+1);

Just insure *buf=&buffer[j] passed into the loop, j is never less than size, or greater than dimension of buffer-size.

Its generally not a libray function as the possibilities of organizing your data, (back looking, forward looking, or your symmetric would be the most common) make paramertizing a general function more complex than a simple direct implimentation of the function.  Not to mentions the issues of various integer sized data vs. doubles etc for the input data.  This way you can make output a double, let automatic promotion convert the intergers and then round or truncate the average back to the integer data if needed or leave the output data in a double array. 

If you set the pointer and size right you can call the library mean or average function for each output point but instead of N-2*size steps in the outer loop to filter N points of a waveform in buffer[] you'd have N-2*size function calls and associated pointer manipulations.  Still likely not an issue with modern processors, but sometimes a direct implimentation of a simple algorithm is the best choice, I'd argue for somthing as simple as a moving average filter, it always is.  If you need to do it a lot, its easy enough to define a macro if cut and paste offends you.

--wally.




Message Edited by wally_666 on 03-03-2008 05:29 PM

Message Edited by wally_666 on 03-03-2008 05:30 PM
Message 8 of 11
(7,049 Views)

Ok, thanks to all for your opinions.

I've made a function to do the moving (running) average, each point of the array is averaged with itself and the values close to it, exept the first and the last points, these point are ony averaged upwards (first) or backwards (last)

The function can be optimized but it works fine.

definition: int MovingAverage( int averaging, double data[] , int size, double retval[] ); 

averaging= the number of times a value is averaged with his "neighbours" upward and backwards

data= array of raw data

size= the size of the data array

retval = the output array

int MovingAverage( int averaging, double data[] , int size, double retval[] )
{
int i,ii;

 size= size-1;
 
 Set1D (retval, size, 0.0);  // Set the output array to 0
 
 for( i=0; i<= averaging ; i++){   //loop to average the first points of the array
  
  for ( ii=0; ii<=averaging; ii++ ){
   retval[i]+= data[i+ii];
  }
  retval[i] = retval[i] / (averaging+1);
 }
 
 for( i=0; i<= averaging ; i++){  //loop to average the last points of the array
  
  for ( ii=0; ii<=averaging-1; ii++ ){
   retval[i+size-averaging] += data[i-ii+size-averaging];
  }
  retval[i+size-averaging] = retval[i+size-averaging] / (averaging+1);
 }
 

 for (i=averaging+1; i<= (size-averaging-1); i++)    //loop to average the middle points of the array
 {
  
  for ( ii=0; ii<=averaging; ii++ ){
   retval[i]+= data[i-ii];
  }
  
  for ( ii=1; ii<=averaging; ii++ ){
   retval[i]+= data[i+ii];
  }
  
  retval[i] = retval[i] / ((2*averaging)+1);
 }
 

return 0;
}

 

Image Hosted by ImageShack.us
Message 9 of 11
(7,026 Views)
Anyone considering a moving average should be aware of the exponentially weighted moving average. It's easier to use and works as well or better than the simple moving average in many situations. It's main advantage, from a programming standpoint, is that it eliminates the need to maintain old data. It also eliminates calculation of the sum for each iteration and is thus very efficient. It places more weight on recent values in calculating the average. The simple moving average gives equal weight to each value.
Message 10 of 11
(6,245 Views)