Most readable syntax to fill table in a for cycle

9 vues (au cours des 30 derniers jours)
f
f le 11 Avr 2023
Commenté : Dr D le 18 Avr 2023
What is the clearest syntax to fill a table entry by entry in a for cycle? For instance, take the following code that checks convergence of a certain iteration.
format short e
x = rand();
T = table();
for k = 1:5
x = 1/2 * (x + 1/x);
T.x(k) = x;
T.residual(k) = abs(x - sign(x));
end
Warning: The assignment added rows to the table, but did not assign values to all of the table's existing variables. Those variables are extended with rows containing default values.
Warning: The assignment added rows to the table, but did not assign values to all of the table's existing variables. Those variables are extended with rows containing default values.
Warning: The assignment added rows to the table, but did not assign values to all of the table's existing variables. Those variables are extended with rows containing default values.
Warning: The assignment added rows to the table, but did not assign values to all of the table's existing variables. Those variables are extended with rows containing default values.
T
T = 5×2 table
x residual __________ __________ 1.3744e+00 3.7445e-01 1.0510e+00 5.1006e-02 1.0012e+00 1.2377e-03 1.0000e+00 7.6500e-07 1.0000e+00 2.9265e-13
This code looks very readable to me, but it has the drawback of displaying lots of spurious warnings.
All other solutions I have found require specifying things in two places; for instance, setting column types and names in advance and then identifying them by position. I find this cumbersome because I would like to be able to specify things in only one place. This code should go in my lecture notes and it is meant for readability and "least surprise", not performance.

Réponse acceptée

Les Beckham
Les Beckham le 11 Avr 2023
There probably isn't a significantly cleaner way to do this. See below for a way to suppress the warnings.
format short e
x = rand();
T = table();
warning('off', 'MATLAB:table:RowsAddedExistingVars')
for k = 1:5
x = 1/2 * (x + 1/x);
T.x(k) = x;
T.residual(k) = abs(x - sign(x));
end
T
T = 5×2 table
x residual __________ __________ 1.1003e+00 1.0032e-01 1.0046e+00 4.5736e-03 1.0000e+00 1.0411e-05 1.0000e+00 5.4197e-11 1.0000e+00 0.0000e+00
Run the line below after running your code once to find out the warning ID, then add the warning('off', ... command above using the id
% [msg, id] = lastwarn
msg = 'The assignment added rows to the table, but did not assign values to all of the table's existing variables. Those variables are extended with rows containing default values.'
id = 'MATLAB:table:RowsAddedExistingVars'
  1 commentaire
Dr D
Dr D le 18 Avr 2023
Note, of course, that you've turned the warning off for the rest of the MatLab session - all code that follows this point. For robustness, MatLab makes it pretty easy to capture the current warning state, then re-set it after the loop. Like this:
oldWarn = warning( 'off', 'MATLAB:table:RowsAddedExistingVars' );
for ...
end
warning( oldWarn );

Connectez-vous pour commenter.

Plus de réponses (2)

Antoni Garcia-Herreros
Antoni Garcia-Herreros le 11 Avr 2023
Hello
You could create the arrays containing x and residual beforehand and create the table afterwards. Something like this:
x=zeros(5,1);
T = table();
x(1)=rand();
for i=2:5
x(i) = 1/2 * (x(i-1) + 1/x(i-1));
end
y=abs(x - sign(x));
T.x=x;
T.residual=y
T = 5×2 table
x residual _______ __________ 0.88046 0.11954 1.0081 0.008115 1 3.2662e-05 1 5.3338e-10 1 0

Dr D
Dr D le 18 Avr 2023
I know you said you don't want to specify the column names & types in advance, but there's one thing to consider for the future. If the table will become very large, adding one row at a time will make the code very slow as the table grows and large blocks of memory have to be reallocated in the background. In professional programming, the acceptable solution is to preallocate your memory. For a table, the best way to do that is to specify the table format in advance, then allocate the entire block of memory one time.
For those who are not familiar, it looks something like the below. Notice how simple it is to specify and preallocate the entire table in only two lines.
(Note, you could do it in one line by specifying a row count in the 'Size' parameter. I find that different versions of MatLab don't properly fill the table with their "missing" values when you do that so since my codes have to run on many different versions, prefer the extra step of explicitly assigning missing().)
T = table( 'Size', [0 2], 'VariableNames', {'x', 'residual'}, 'VariableTypes', {'double','double'} );
T{1:5,:} = missing();
for k = 1:height(T)
...

Catégories

En savoir plus sur Logical dans Help Center et File Exchange

Tags

Produits


Version

R2023a

Community Treasure Hunt

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

Start Hunting!

Translated by