MATLAB Answers

Return vectors from for loop as columns in matrix

4 views (last 30 days)
Emma Kuttler
Emma Kuttler on 21 Nov 2019
Commented: Jan on 22 Nov 2019
Hi, I have a 296x6 matrix called normalimpact, and i want to assign random weights to each column of the matrix, do some scoring and ranking operations, and repeat this for a certain number of trials (say 10), and ouput the result from each trial (the column vector RankOfNode) as a column in a matrix. Each iteration's result of RankOfNode) should be its own column in a final matrix.
I'm just confused as how to implement the index for the number of runs into this code, since there already are a lot of for loops and indices.
normalimpact = horzcat(NormalPowerN1f, NormalICTN1f, NormalPowerN2f, NormalICTN2f, NormalPowerN3f, NormalICTN3f);
% for loop to do a bunch of runs of this code with different weights each time????
% weight the matrix, giving a weight to each column
weights = rand(1,6);
weights = weights / sum(weights);
normalimpactw = bsxfun(@times, normalimpact, weights);
max_vals = max(normalimpactw); % maximum values of each colum(1 to 6 )
Dplus = zeros(size(normalimpactw,1), 1); % initialize
for ii =1: size(normalimpactw, 1 )
Dplus(ii, :) = sqrt(sum([normalimpactw(ii,:)-max_vals].^2 ));
end
Dplus; % column matrix after calculation
min_vals = min(normalimpactw); % minimum values of each column(1 to 6 )
Dminus = zeros(size(normalimpactw,1), 1); % initialize
for ii =1: size(normalimpactw, 1 )
Dminus(ii, :) = sqrt(sum([normalimpactw(ii,:)-min_vals].^2 ));
end
Dminus; % column matrix after calculation
% give score to each row of matrix based on values for Dplus and Dminus
Sscore = zeros(size(Dminus,1),1);
for n=1:296
Sscore(n,:) = Dminus(n,:)/(Dminus(n,:)+Dplus(n,:));
end
% produces the rank for each node, ie node 1 has rank 50, node 2 has rank 23
[~,rank] = ismember(Sscore,sort(Sscore,'descend'));
RankOfNode = rank;
% end of for loop????

  0 Comments

Sign in to comment.

Answers (1)

Jan
Jan on 21 Nov 2019
Edited: Jan on 22 Nov 2019
Start with cleaning up the code.
  • The lines Dplus; and Dminus; do nothing, so they are wasting time only and confuse the readers.
  • Are you running a Matlab version >= R2016b? Then you can omit the bsxfun() calls and use implicit expanding.
  • The loops can be omitted also:
% Replace:
Dminus = zeros(size(normalimpactw,1), 1); % initialize
for ii =1: size(normalimpactw, 1 )
Dminus(ii, :) = sqrt(sum([normalimpactw(ii,:)-min_vals].^2 ));
end
Dminus;
% by
Dminus = vecnorm(normalimpactw - min_vals, 2, 2);
% Or with older Matlab versions:
tmp = bsxfun(@minus, normalimpactw, min_vals);
Dminus = sqrt(sum(tmp .^2, 2));
  • Do you really need ismember, or do you want the sorting order?
Together:
normalimpact = horzcat(NormalPowerN1f, NormalICTN1f, NormalPowerN2f, NormalICTN2f, NormalPowerN3f, NormalICTN3f);
% for loop to do a bunch of runs of this code with different weights each time????
% weight the matrix, giving a weight to each column
weights = rand(1,6);
weights = weights / sum(weights);
normalimpactw = normalimpact .* weights;
max_vals = max(normalimpactw); % maximum values of each colum(1 to 6 )
Dplus = vecnorm(normalimpactw - max_vals, 2, 2);
min_vals = min(normalimpactw); % minimum values of each column(1 to 6 )
Dminus = vecnorm(normalimpactw - min_vals, 2, 2);
Sscore = Dminus ./ (Dminus + Dplus);
% Is this meant? ^^ elementwise devision?
[~, RankOfNode] = sort(Sscore,'descend');
Now including this in a for loop might be easier.
for k = 1:10
...
[~, RankOfNode(k, :)] = sort(Sscore, 'descend');
% [EDITED] ^ orphaned "]" removed here
end
Or maybe you want to collect the output in a cell array?

  2 Comments

Emma Kuttler
Emma Kuttler on 21 Nov 2019
Thanks for your help! I think i do need to use ismember in order to break ties. Is there a way to use my original sorting code with a loop? The rest of the cleanup works well and returns the same values.
[~,rank] = ismember(Sscore,sort(Sscore,'descend'));
RankOfNode = rank;
Additionally, your suggestion of
for k = 1:10
...
[~, RankOfNode(k, :])] = sort(Sscore, 'descend');
end
does not work, it returns:
Invalid expression. When calling a function or indexing a variable, use parentheses. Otherwise, check for mismatched delimiters.
When i remove a parentheses or bracket, it give me an error of:
Unable to perform assignment because the size of the left side is 1-by-1 and the size of the right side is 296-by-1.
Jan
Jan on 22 Nov 2019
@Emma: There was a typo in my code and the "]" must be removed. collecting the data inside RankOfNode works only, if this variables is pre-allocated with the matching size. So either use:
RankOfNode = zeros(296, 10);
for k = 1:10
% the rest of the code comes here
[~, RankOfNode(:, k)] = sort(Sscore, 'descend');
end
Or collect the values in a cell array at first:
RankOfNodeC = cell(1, 10);
for k = 1:10
% the rest of the code comes here
[~, RankOfNodeC{k}] = sort(Sscore, 'descend');
end
RankOfNode = cat(2, RankOfNodeC{:});

Sign in to comment.