Average matrix columns until convergence

7 次查看(过去 30 天)
I have a matrix of positions for separate runs (column 1 is run 1, column 2 is run 2, etc.). How can I take an average of the positions at each row for each run until the average converges within a set criteria? For example, if I only did 1 run:
x = [ 5.0040; 5.0072; 5.0120; 5.0173]
avg = [5.0040 5.0072 5.0120 5.0173]
If I have 2 runs:
x = [5.0040 5.1710; 5.0072 5.1724; 5.0120 5.1784; 5.0173 5.1896]
avg = [5.0875 5.0898 5.0952 5.1035]
Id like to take the difference of the previous average and the "new" average and select the MAX value. Once the max value is under a specified value, break out of the loop. This will tell me that I have done enough runs to know a confident position array.
Here's some code I have been working on:
x = A(:,2:5:end);
[height, width] = size(x);
S = 1;
prev = 0;
while S > 0.01
for i = 1:length(x)
for j = 1:width
avg(i) = mean(x(i,j))
diff = avg - prev
S = max(avg)
prev = avg
end
end
end

采纳的回答

Guillaume
Guillaume 2017-5-4
There's no need for a loop. Compute the cumulative average of the rows, use diff on that and compute the max of each column. The first column at which your max is below the threshold is the column you're looking for:
%x: input matrix
%threshold: maximum allowed difference allowed between cumulative means
cummean = cumsum(x, 2) ./ (1:size(x, 2)); %requires R2016b or later. For earlier versions use bsxfun for the division
maxdelta = max(diff(cummean, [], 2));
runsrequired = find(maxdelta < threshold, 1)
A few notes about the code you've written:
  • Don't use diff as a variable name since it prevents you from using the very useful diff function (and you better clear it if you want my code to run).
  • Never use length with 2D matrix (and even with vectors, prefer <https://www.mathworks.com/help/matlab/ref/numel.html numel). Your code will break if x has more columns than rows since length will then return the number of columns when you clearly meant to iterate over the rows. In your case, use the height variable that you've created and never used or even simpler, simply query the height in the loop with size(x, 1). I.e: don't bother with your [width, height] = size(x); and use
for i = 1:size(x, 1) %and I would use row instead of i
for j = 1:size(x, 2) %and I would use col instead of j
%and whenever possible iterate over the rows in the inner loop rather the outer one. It'll be faster
  • avg(i) = mean(x(i, j)) Not sure what you intended with that. The mean of a scalar value is simply that value.
  1 个评论
Shawn Smearcheck
Shawn Smearcheck 2017-5-4
Thanks for the advice. This works much better than a loop. the cumsum function is very helpful.

请先登录,再进行评论。

更多回答(0 个)

类别

Help CenterFile Exchange 中查找有关 Matrix Indexing 的更多信息

Community Treasure Hunt

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

Start Hunting!

Translated by