Effacer les filtres
Effacer les filtres

Put values from an array in a while loop into a table

18 vues (au cours des 30 derniers jours)
Vladislavs Grigorjevs
Vladislavs Grigorjevs le 6 Avr 2022
I have a while loop that produces an array of values in each iteration. What I need is for this array to be output in tabular form, ideally into an Excel table, into a new row for each iteration. Here's what the while loop looks like:
while any(maxnrep~=0)
f = [zeros(1,n) 1];
intcon = 1:n;
% A*w + x == s
Aeq = [A 1];
beq = s;
lb = [zeros(1,n) 0];
hb = [maxnrep, Inf];
wx = intlinprog(f, intcon, [], [], Aeq, beq, lb, hb, options);
% number of coins to approximate s
w=round(wx(1:n))';
% the residual x
x = s - sum(w.*A); % == wx(n+1)
if any(w~=y)
iterCount_sub=iterCount-iterCount_sub;
if c~=1
fprintf ('Repeat %.0f times \n', iterCount_sub)
end
fprintf ('\nWay number %.0f\n', c);
fprintf(['%.1f = ' repmat('%.1d*%.0f + ', 1, n) '%.0f\n'], s, [w; A], x)
c=c+1;
iterCount_sub=iterCount;
end
maxnrep = maxnrep - w;
y=w;
iterCount=iterCount+1;
end
The array I need to get into a table is w. I also need separate columns for x and iterCount_sub. As of now, the output looks like this:
Way number 1
12000.0 = 0*6690 + 0*4740 + 0*5990 + 0*6540 + 0*4840 + 0*3240 + 3*4000 + 0
Repeat 609 times
Way number 2
12000.0 = 0*6690 + 1*4740 + 0*5990 + 0*6540 + 0*4840 + 1*3240 + 1*4000 + 20
Repeat 2 times
Way number 3
12000.0 = 0*6690 + 0*4740 + 2*5990 + 0*6540 + 0*4840 + 0*3240 + 0*4000 + 20
Repeat 120 times
etc..
Here, each value that goes before the * sign is part of the w array, and each value that goes after it is part of the A array, the values for which are input by the user.
What I need in the end should look something like this, along with an Excel table:
6690 4740 5990 6540 4840 3240 4000 x rep. count
---- ---- ---- ---- ---- ---- ---- --- ----------
0 0 0 0 0 0 3 0 609
0 1 0 0 0 1 1 20 2
0 0 2 0 0 0 0 20 120
% Is this possible?

Réponse acceptée

Stephen23
Stephen23 le 6 Avr 2022
Modifié(e) : Stephen23 le 6 Avr 2022
There is no need to create lots of separate vectors, doing so would be very inefficient.
Much simpler to convert the matrix using ARRAY2TABLE and then save the table. Note that the table variable/columns names do not need to have 'c' as lead character.
M = [0,0,0,0,0,0,3,0,609;0,1,0,0,0,1,1,20,2;0,0,2,0,0,0,0,20,120]
M = 3×9
0 0 0 0 0 0 3 0 609 0 1 0 0 0 1 1 20 2 0 0 2 0 0 0 0 20 120
S = ["6690","4740","5990","6540","4840","3240","4000","x","rep.count"];
T = array2table(M,'VariableNames',S)
T = 3×9 table
6690 4740 5990 6540 4840 3240 4000 x rep.count ____ ____ ____ ____ ____ ____ ____ __ _________ 0 0 0 0 0 0 3 0 609 0 1 0 0 0 1 1 20 2 0 0 2 0 0 0 0 20 120
writetable(T,"coefficienttable.xlsx")
  5 commentaires
Stephen23
Stephen23 le 6 Avr 2022
"Is there any way I could suppress that first 0 value and move all of the values up 1 row?"
You could either modify your code to include that offset, or modify the data after the loop, e.g. something like this:
M(:,end) = [M(2:end,end);NaN];
The last row doesn't need a rep.count value."
But numeric arrays cannot have "holes" in them, so there has to be some value there. What value depends on you. As an alternative you could replace the entire table column/variable with a cell array of scalar numerics and place an empty array in the last cell.
Vladislavs Grigorjevs
Vladislavs Grigorjevs le 6 Avr 2022
This works perfectly, thank you so much once again!

Connectez-vous pour commenter.

Plus de réponses (1)

Simon Allosserie
Simon Allosserie le 6 Avr 2022
To put info in tables, you best put them in columns. So you could define coefficient vectors for each coefficient, and through your loops add values to these column vectors. In your example, they would look like this
c6690 = [0 0 0]' %a variable name can't start with a number, so I start the name with c(oefficient)
c4740 = [0 1 0]'
c5590 = [0 0 2]'
..
repcount = [609 2 120]'
T = table(c9960, c4740, .., repcount)
Next write it to Excel using writetable (see https://nl.mathworks.com/help/matlab/ref/writetable.html)
writetable(T,"coefficienttable.xlsx")
That should do the trick.
  3 commentaires
Simon Allosserie
Simon Allosserie le 6 Avr 2022
In that case, you could make one matrix instead of column matrices, where the size is dependent on the user input. The user should then also give the column names such that you can define the table as
T = table(M, 'VariableNames', {'c6690','c4740', .., 'repcount'})
Of course, you can also create the variableNames yourself by converting the coefficients to text with num2str() and adding 'c' before it with strcat()
For the length of the vectors/size of the matrix, there are multiple options.
1) You can predefine the length very largely, e.g.
c = zeros(1000,1)
after calculations, you can shorten the matrices to delete the zero elements.
2) You can just add elements in each iteration
c(i) = value
and in the case c is 10 long, and you add c(11), matlab will automatically make c longer to be able to add this element on that location. The drawback here is that this takes a lot of time, so option (1) is recommended.
Stephen23
Stephen23 le 6 Avr 2022
"...you can define the table as T = table(M, 'VariableNames', {'c6690','c4740', .., 'repcount'})"
No, that will not work. Lets try it with a simple example:
M = rand(5,3);
T = table(M, 'VariableNames', {'c6690','c4740','repcount'})
Error using table
The VariableNames property must contain one name for each variable in the table.
Why does it not work? Because it creates a table with one variable/column, but then attempts to name three variables. Thus the number of variable names does not match the number of variables/columns, as the error clearly states.

Connectez-vous pour commenter.

Catégories

En savoir plus sur Loops and Conditional Statements dans Help Center et File Exchange

Produits


Version

R2022a

Community Treasure Hunt

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

Start Hunting!

Translated by