Create a zero matrix and update cells based on other column values

8 vues (au cours des 30 derniers jours)
Sunny
Sunny le 20 Déc 2018
Commenté : Sunny le 20 Déc 2018
Hi,
I have a matlab table (attached in this thread) named 'List' (matlab table format) with 5 columns as shown below. I am looking to create a zero matrix for each unique subject value in a struct, Every matrix has fixed rows 102, but column size depends on the sum of values in 'Steps' column for that subject. For example, for subject 9 the zero matrix is 102x45. Here 45 is based on sum of 15+20+10 in Steps column, and for subject 10 the matrix is 102x13 where 13 columns are from sum of 5 + 8. Once these matrices are created, I am trying to pick the value from ANS column on each row and place it in the zero matrix related to subject. For example, when we scan first row which is subject 9, the value in ANS is -1, this is placed in Zero matrix relevant to subject 9 at row 10 (based on 'ID' column in the table) and in the 15 columns (-1 will be in 10x1,10x2,..10x15) this is based on the value in Steps column. The next row it starts at row 8 and coulmn 16 as we used till column 15 earlier and this continues till 20 values of 1 are place in (8x16....8x15) and this repeats till all data related to subject 9 is populated. This loops for all the subjects.
List : Format type Table
Subject Number ID ANS Steps
9 1 10 -1 15
9 2 8 1 20
9 3 10 -1 10
10 1 5 1 5
10 2 6 -1 8

Réponse acceptée

Guillaume
Guillaume le 20 Déc 2018
I would do it like this:
First create a function to create a matrix, given column vectors of ids, ans, and steps for a single subject (I'm using more meaningful variable names. You certainly shouldn't call a variable ans):
%saved in its own m file:
function m = makeMatrix(rows, values, ncols)
m = zeros(102, sum(ncols)); %create matrix full of zeros
m(sub2ind(size(m), repelem(rows, ncols), (1:sum(ncols))')) = repelem(values, ncols);
end
It is then easy to apply that to any table using rowfun:
%demo table:
t = array2table([9 1 10 -1 15
9 2 8 1 20
9 3 10 -1 10
10 1 5 1 5
10 2 6 -1 8], ...
'VariableNames', {'Subject', 'Number', 'ID', 'ANS', 'Steps'});
%apply function
c = rowfun(@makeMatrix, t, 'GroupingVariables', 'Subject', 'InputVariables', {'ID', 'ANS', 'Steps'}, 'OutputFormat', 'cell');
You can then transforim that output cell array into a structure:
s = cell2struct(c, compose('Subject%d', unique(t.Subject)), 1)
  5 commentaires
Guillaume
Guillaume le 20 Déc 2018
Isn't it obvious? A lot of your steps are not integer. Perhaps, you should round the values:
list.Steps = round(list.Steps);
Sunny
Sunny le 20 Déc 2018
ohh yes, I missed this. Thanks

Connectez-vous pour commenter.

Plus de réponses (1)

Bob Thompson
Bob Thompson le 20 Déc 2018
I'm going to take a stab at what you're looking for here, let me know if I need to adjust something.
I'm going to begin with the assumption that you can get your data into an array (without labels) with the arrangement shown above.
for i = unique(List(:,1));
block = List(List(:,1)==i,:)
[Grades(i).data] = zeros(102,sum(block(:,5)));
col = 1;
for j = 1:size(block,1);
[Grades(i).data(block(j,3),col:col+block(j,5)-1)] = block(j,4);
col = col+block(j,5);
end
end
  1 commentaire
Sunny
Sunny le 20 Déc 2018
Modifié(e) : Sunny le 20 Déc 2018
Will try this. Can you check and inform what I am doing wrong in this? Error, Matrix dimensions must agree
Subject = [9;9;9;10;10];
Number = [1;2;3;1;2];
ID = [10;10;10;5;6];
ANS = [-1;1;-1;1;-1];
Steps = [15;20;10;5;8];
List = table(Subject,Number,ID,ANS,Steps);
List = table2array(List)
for i = unique(List(:,1))
block = List(List(:,1)==i,:);
[Grades(i).data] = zeros(102,sum(block(:,5)));
col = 1;
for j = 1:size(block,1)
[Grades(i).data(block(j,3),col:col+block(j,5)-1)] = block(j,4);
col = col+block(j,5);
end
end

Connectez-vous pour commenter.

Catégories

En savoir plus sur Logical dans Help Center et File Exchange

Produits


Version

R2018a

Community Treasure Hunt

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

Start Hunting!

Translated by