필터 지우기
필터 지우기

Most readable syntax to fill table in a for cycle

조회 수: 14 (최근 30일)
f
f 2023년 4월 11일
댓글: Dr D 2023년 4월 18일
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.

채택된 답변

Les Beckham
Les Beckham 2023년 4월 11일
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
Dr D
Dr D 2023년 4월 18일
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 );

댓글을 달려면 로그인하십시오.

추가 답변 (2개)

Antoni Garcia-Herreros
Antoni Garcia-Herreros 2023년 4월 11일
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 2023년 4월 18일
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)
...

카테고리

Help CenterFile Exchange에서 Loops and Conditional Statements에 대해 자세히 알아보기

태그

제품


릴리스

R2023a

Community Treasure Hunt

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

Start Hunting!

Translated by