Return vectors from for loop as columns in matrix

3 views (last 30 days)
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????

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.

Categories

Find more on Operating on Diagonal Matrices in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!