Average matrix columns until convergence

조회 수: 6 (최근 30일)
Shawn Smearcheck
Shawn Smearcheck 2017년 5월 4일
댓글: Shawn Smearcheck 2017년 5월 4일
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