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

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

Accepted Answer

Guillaume on 20 Dec 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);
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)

Sign in to comment.

More Answers (1)

Bob Thompson
Bob Thompson on 20 Dec 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);
  1 Comment
Sunny on 20 Dec 2018
Edited: Sunny on 20 Dec 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);

Sign in to comment.


Find more on Tables 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!

Translated by