How do I take the average of every n values in a vector?

I have some data on Pulse Rate and the sample was taken at 1000 Hz (One sample every millisecond), way too big for what I want to see. My vector is 399277x1 and I want to be able to average every 1000 values and get that number in a new vector of somewhere around 400x1. Is there any way to do this?
Thanks

 Accepted Answer

Try this...
n = 1000; % average every n values
a = reshape(cumsum(ones(n,10),2),[],1); % arbitrary data
b = arrayfun(@(i) mean(a(i:i+n-1)),1:n:length(a)-n+1)'; % the averaged vector

9 Comments

So the name of my current vector is "PulseRateF". It's dimensions are 399277 x 1. Where do I incorporate my vector into the code lines?
Does that make sense? I tried that but I think that it made a vector from generic, or arbitrary, data.
Thank you for your help
Yes, I just created arbitrary data in a variable called a. In your case, replace all the a's in the 3rd line of code (b = arrayfun...) with PulseRateF.
I really appreciate this answer! Thank you!
Note one difference. My answer below using blockproc() gets the average of the final 277 elements, even though it's not a full block of 1000, while Matthew's does not (it skips those values).
So Matthews array and Jan's result are 399 long, while mine and Andrei's results are the full 400 long.
You have to decide what you want. Do you want the average of the final, partial block, or not?

Sign in to comment.

More Answers (4)

Jan
Jan on 28 Jun 2013
Edited: Jan on 17 May 2019
x = rand(399277, 1); % Some example data
n = 1000; % Number of elements to create the mean over
s1 = size(x, 1); % Find the next smaller multiple of n
m = s1 - mod(s1, n);
y = reshape(x(1:m), n, []); % Reshape x to a [n, m/n] matrix
Avg = transpose(sum(y, 1) / n); % Calculate the mean over the 1st dim

10 Comments

@Jan
What this actually does? Does it average in a step of n intervals along the x axis? This is what I am looking for. Hope this does what I want.
I want to divide the x axis into intervals and average between them.
And why if I put n = 1000 I get a single result as outcome while when I put low number such as 10 or 20, I get multiple outcomes.
Is this code similar to moving mean (movmean)?
Jan
Jan on 13 May 2019
Edited: Jan on 13 May 2019
This code claculates the mean values of n elements. Therefore the input vector x is cropped at first, such that it has a multiple of n elements.
The code has no relation to any "x axis", because no graphics are involved here.
How can I modify it to do the same job involving intervals of x axis for 2d plots?
I do not have any idea, what the relation to an x axis of a 2D plot is and what you mean by intervals.
The code I have posted calculates the mean value over blocks of n elements of a vector. The input data is a vector and teh output is also. An x axis of a 2D plot is a graphical interface with a direction, some tick marks and lables, a title and different methods to display the lables.
If you want me to understand, what a blockwise averaging has to do with "involving intervals of x axis for 2d plots", you have to explain this at first.
Sorry. My misinterpratation. When I say "x axis", I meant the data on the x axis, which are numeric values that correspond to certain y values.
How you interpret blockwise (blocks of n elements?). I have the sense that we tell the same thing.
Imagine there is an array of n elements, distributed in the x coordinate. You split them into intervals and average each interval seperately and then alltogether? How are you actually doing this?
@Stelios: It is not clear what "data on the x axis" should be. I guess you mean a trivial object called "vector", e.g.:
x = rand(1, 100)
This is a vector of 100 elements. Altough it is called "x", it does not have any relation to an axis. You can call it bananaProduction also. You cannot claim, that these vales are "distributed in the x coordinate", because this term is not even meaningful in a mathematical sense.
You see in the code I have posted, how it is treated in blocks of n elements, let's use e.g. 5. Then the 1D vector can be reshaped efficiently into a 2D matrix with 5 rows and 20 columns:
y = reshape(x, 5, 20);
To create the mean over the columns, Matlab offers the command mean() and let us specify the dimension to operate on:
avg_x = mean(y, 1);
In my code I've used sum(M, 1) / n, because it is sligthtly faster, but of course we get the same result.
The code in my answer considers in addition that the number of elements of x need not be a multiple of n. Then
s1 = size(x, 1);
M = s1 - mod(s1, n) % next smaller mutliple of n
Is the next smaller mutliple of n, such that the number of elements in x(1:M) is divisable by n.
Stelios, my code has 4 lines only and it uses only very basic Matlab commands. Therefore it is hard to answer "How are you actually doing this?"
@Jan
Thanks for your thoroughtly explanation on your code.
x = rand(399277, 1); % Some example data
n = 1000; % Number of elements to create the mean over
s1 = size(x, 1); % Find the next smaller multiple of n
m = s1 - mod(s1, n);
y = reshape(x(1:m), n, []); % Reshape x to a [n, m/n] matrix
Avg = transpose(sum(y, 1) / n);
Although, it is consist of 6 simple code lines I wasn't familiar with the though behind it.
For instance, in this case, as your example data you used a vector of 399277 rows in a single column. You chose to find the mean per 1000 elements (n). I didn't quite understand why you are trying to find the next smaller multiple of n. I suppose you want integers to perfectly divide the x and not decimals. Am I correct?
You then reshape the matrix for faster computation, probably?
And what this transpose stands for? You calculate the mean over the first dimension of y, since the second one is the n. Right?
Always, welcome your explanations
Hello Jan,
The code worked wuite perfect for me. I need a small modification in that. The created Avg double by you code is of the size 'data_double' / n. For example, I have data of 11329 x1 double and for n = 10, I have the Avg double of 1132 x 1. But since I want to plot my original data and the Avg data on same graph, I need to make the Avg double size same .ie. 11329 x 1 where the mean value can repeat itself for value of n and then change to next mean value. Can you help me with this modification ?
Thank you,
Laukik.
@Laukik Avinash Kharche: I assume, this helps:
Avg = repelem(Avg, 10, 1);

Sign in to comment.

Here is how I'd do it (an alternate way), using blockproc to average in 100 element long blocks in "jumps":
% Create sample data
PulseRateF = rand(399277, 1);
% Define the block parameter. Average in a 100 row by 1 column wide window.
blockSize = [1000, 1];
% Block process the image to replace every element in the
% 100 element wide block by the mean of the pixels in the block.
% First, define the averaging function for use by blockproc().
meanFilterFunction = @(theBlockStructure) mean2(theBlockStructure.data(:));
% Now do the actual averaging (block average down to smaller size array).
blockAveragedDownSignal = blockproc(PulseRateF, blockSize, meanFilterFunction);
% Let's check the output size.
[rows, columns] = size(blockAveragedDownSignal)

5 Comments

That also worked. Thank you
@Image Analyst
What this actually does? Does it average in a step of n intervals along the x axis? This is what I am looking for. Hope this does what I want.
I want to divide the x axis into intervals and average between them.
It scans a window, of 1000 elements long, along the array in "jumps" of 1000, taking the average of those 1000 elements in the array. Thus the result will be the means in an array 1/1000 of the length of the original array. It should do what you want. It's just an alternative way to doing it via reshape() like Jan suggested. This has the advantage that the array does not need to be a multiple of 1000 long to work (it will just average whatever remainder is left at the right end of hte array), and it can be configured to do a scan of a 2-D matrix if you have that situation.
I am not sure whether I understood it well. I use this
% Create sample data
PulseRateF = Pd;
% Define the block parameter. Average in a 100 row by 1 column wide window.
blockSize = [300, 100];
% Block process the image to replace every element in the
% 100 element wide block by the mean of the pixels in the block.
% First, define the averaging function for use by blockproc().
meanFilterFunction = @(theBlockStructure) mean2(theBlockStructure.data(:));
% Now do the actual averaging (block average down to smaller size array).
blockAveragedDownSignal = blockproc(PulseRateF, blockSize, meanFilterFunction);
% Let's check the output size.
[rows, columns] = size(blockAveragedDownSignal)
And I get
rows = 5 columns = 1
What those numbers mean?
Look at the code: These numbers are the size of the variable blockAveragedDownSignal.

Sign in to comment.

x = randi(1000,399277,1);
n = 1000;
m = numel(x);
out = nanmean(reshape( [x(:);nan(mod(-m,n),1)],n,[]));
or
out = accumarray(ceil((1:numel(x))/1000)',x(:),[],@mean);

3 Comments

This answer is simple and perfect. Thanks!
@Andrei Bobrov
What this actually does? Does it average in a step of n intervals along the x axis? This is what I am looking for. Hope this does what I want.
I want to divide the x axis into intervals and average between them.

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!