How do I take the average of every n values in a vector?
Show older comments
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
More Answers (4)
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
Stelios Fanourakis
on 13 May 2019
Edited: Stelios Fanourakis
on 13 May 2019
@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)?
Stelios Fanourakis
on 15 May 2019
How can I modify it to do the same job involving intervals of x axis for 2d plots?
Jan
on 16 May 2019
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.
Stelios Fanourakis
on 16 May 2019
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?"
Stelios Fanourakis
on 19 May 2019
Edited: Stelios Fanourakis
on 19 May 2019
@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
Laukik Avinash Kharche
on 23 Jun 2022
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.
Jan
on 23 Jun 2022
@Laukik Avinash Kharche: I assume, this helps:
Avg = repelem(Avg, 10, 1);
Laukik Avinash Kharche
on 1 Jul 2022
Thanks a lot, it worked.
:)
Image Analyst
on 27 Jun 2013
Edited: Image Analyst
on 5 Jan 2019
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
Brooks
on 27 Jun 2013
Stelios Fanourakis
on 13 May 2019
@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.
Image Analyst
on 13 May 2019
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.
Stelios Fanourakis
on 16 May 2019
Edited: Stelios Fanourakis
on 16 May 2019
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?
Jan
on 16 May 2019
Look at the code: These numbers are the size of the variable blockAveragedDownSignal.
Andrei Bobrov
on 28 Jun 2013
Edited: Andrei Bobrov
on 28 Jul 2017
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
Shannon Ross-Sheehy
on 2 Mar 2019
This answer is simple and perfect. Thanks!
Stelios Fanourakis
on 13 May 2019
@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.
Imran Yasin
on 31 Jul 2020
Very nice job!
Categories
Find more on String in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!