Average matrix columns until convergence

7 vues (au cours des 30 derniers jours)
Shawn Smearcheck
Shawn Smearcheck le 4 Mai 2017
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

Réponse acceptée

Guillaume
Guillaume le 4 Mai 2017
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 commentaire
Shawn Smearcheck
Shawn Smearcheck le 4 Mai 2017
Thanks for the advice. This works much better than a loop. the cumsum function is very helpful.

Connectez-vous pour commenter.

Plus de réponses (0)

Catégories

En savoir plus sur Matrix Indexing dans Help Center et File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by