MATLAB Answers

Brooks
1

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

Brooks
さんによって質問されました 2013 年 6 月 27 日
最新アクティビティ Stelios Fanourakis さんによって 編集されました 2019 年 5 月 19 日
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

  0 件のコメント

サインイン to comment.

5 件の回答

回答者: Matthew Eicholtz 2013 年 6 月 27 日
 採用された回答

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

  8 件のコメント

ALI DASMEH 2019 年 1 月 5 日
Thanks alot Man!
Image Analyst
2019 年 1 月 5 日
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?
Adoniram
2019 年 1 月 5 日
COOL! thank you

サインイン to comment.


Jan
回答者: Jan
2013 年 6 月 28 日
編集済み: Jan
2019 年 5 月 17 日

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

  7 件のコメント

Stelios Fanourakis 2019 年 5 月 16 日
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?
Jan
2019 年 5 月 17 日
@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 2019 年 5 月 19 日
@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

サインイン to comment.


Image Analyst
回答者: Image Analyst
2013 年 6 月 27 日
編集済み: Image Analyst
2019 年 1 月 5 日

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 件のコメント

Image Analyst
2019 年 5 月 13 日
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 2019 年 5 月 16 日
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
2019 年 5 月 16 日
Look at the code: These numbers are the size of the variable blockAveragedDownSignal.

サインイン to comment.


Andrei Bobrov
回答者: Andrei Bobrov
2013 年 6 月 28 日
編集済み: Andrei Bobrov
2017 年 7 月 28 日

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);

  2 件のコメント

Shannon Ross-Sheehy 2019 年 3 月 2 日
This answer is simple and perfect. Thanks!
Stelios Fanourakis 2019 年 5 月 13 日
@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.

サインイン to comment.


Aubai
回答者: Aubai
2017 年 1 月 20 日

  1 件のコメント

Alexey
2018 年 11 月 1 日
Great solution! Thanks!

サインイン to comment.



Translated by