Reputation: 81
I found another person that asked the same question but the answer was not applicable for an arbitrary length vector.
Averaging every n elements of a vector in matlab
The problem:
x=[1:12]; y=% The averaging operation; After the operation, y=[2 2 2 5 5 5 8 8 8 11 11 11] Therefore the produced vector is the same size, and the jumping average every 3 values replaces the values that were used to produce the average (i.e. 1 2 3 are replaced by the average of the three values, 2 2 2). Is there a way of doing this without a loop?
But what if the vector x is arbitrary (in my case e.g. 500001) and you would like to scale it down arbitrary, e.g. take average over 1000 samples... Is there no ready-matlab function for this, it seems to be a standard problem?
Upvotes: 0
Views: 290
Reputation: 2205
The following code gives you the "jumping average" for any filter-length n
and any data-length N
. For the code to work, N
must be evenly divisible by n
. (Jumping average is not a standard term. I made that up. For me this filter is like a "moving average", but instead of moving continuously, you jump.)
x = 1:20; % so N=length(x) is 20
n = 5; % filter length
xx = reshape(x,n,[]);
yy = sum(xx,1)./size(xx,1);
y = reshape(repmat(yy, size(xx,1),1),1,[]);
If N were 21, for example, then N is no longer divisble by n and this code would return an error. The deeper reason is that there is no obvious way how to handle the edges in this case. Since you have a lot of data-points, I would just throw the last few away.
x = 1:21;
N = length(x);
throw_away = mod(N,n)-1;
x(end-throw_away:end) = []
xx = reshape(x,n,[]);
yy = sum(xx,1)./size(xx,1);
y = reshape(repmat(yy, size(xx,1),1),1,[]);
This should give you the result that you want. However, I would advise you ditch this method altogether, and instead use the standard functions for smoothing data. You can either use the built-in digital filtering function, or implement a simple moving average filter using a convolution. Here is the code for both:
x = 1:21;
n=5;
y1 = filter(ones(1,n)/n, 1, x);
y2 = conv(x, ones(1,n)/n,'valid');
If you look at y1 you'll notice that it lags behind the input data, which is a standard property of digital filters. This "phase delay" is n/2 points.
If you look at y2, you'll note that the vector is shorter than the input vector by (n-1). That's because this particular call only gives back those values, where the moving average could be computed fully.
As you see, there are many different ways to handle the data around the edges, but in the real world, these edge-cases rarely matter.
Upvotes: 1