What is the best way to add empty rows to an existing table, to pre-allocate for more data?

149 views (last 30 days)
Let's say I have a table that has 100 rows of ten variables and now I know I am going to need another 100 rows (or perhaps 100,000) in this table. To avoid loads of copying, I should preallocate these rows before populating them. The variables can be of various different types. I tried doing the following without success:
T{101:200,:} = missing;
I also tried:
T(101:200,:) = cell(100, width(T));
"Conversion to char from cell is not possible."
I just want the equivalent of T.addemptyrows(100). Or, if Matlab had an emptyrow(T) function, I could do:
T(101:200,:) = emptyrow(T)
Here's a toy example to play with:
T = table(["One"; "Two"; "Three"], [1; 2; 3], ['the'; 'cat'; 'sat'], {{1 2 3}; {4 5 6}; {7 8 9}})
T{4:10,:} = missing
Error using {}
Unable to perform assignment because value of type 'missing' is not convertible to 'char'.
Caused by:
Error using char
Conversion to char from missing is not possible.
If I remove the char variable, the same happens with cell.
I considered that I could take the first line of the table and duplicate it 100 times, then overwrite it one line at a time, but this is very inefficient, because cells could contain large amounts of data when all I really want is an empty variable. Additionally, this could hide errors since cells could appear to be populated with viable data when they wouldn't have been, and also could pose serious privacy and security risks in some scenarios.
I could, presumably, write a function that loops through the variable types of each and every variable in the existing table, and then creates a new table of the approriate size and variable types, and then copies the variable names from the first table, and then joins the two tables together, but that is a mess. I also worry about clobbering existing meta data or column data (since several variables could be in one column) and other issues I'm not even aware of. Is there not a more elegant solution? This must be a common thing to need to do. Thanks!

Accepted Answer

Matt J
Matt J on 8 Jan 2024
T = table(["One"; "Two"; "Three"], [1; 2; 3], ['the'; 'cat'; 'sat'], {{1 2 3}; {4 5 6}; {7 8 9}})
T = 3×4 table
Var1 Var2 Var3 Var4 _______ ____ ____ __________ "One" 1 the {1×3 cell} "Two" 2 cat {1×3 cell} "Three" 3 sat {1×3 cell}
newlength=10;
T(newlength+1,:)=T(1,:);
T(end,:)=[]
T = 10×4 table
Var1 Var2 Var3 Var4 _________ ____ ____ ____________ "One" 1 the {1×3 cell } "Two" 2 cat {1×3 cell } "Three" 3 sat {1×3 cell } <missing> 0 {0×0 double} <missing> 0 {0×0 double} <missing> 0 {0×0 double} <missing> 0 {0×0 double} <missing> 0 {0×0 double} <missing> 0 {0×0 double} <missing> 0 {0×0 double}
  4 Comments
Leon
Leon on 8 Jan 2024
"Copying cells doesn't result in any new memory consumption. It's all done with pointers."
That's great, I didn't realise that. So your solution is very good. Thanks!

Sign in to comment.

More Answers (1)

Voss
Voss on 7 Jan 2024
Edited: Voss on 7 Jan 2024
T = table(["One"; "Two"; "Three"], [1; 2; 3], ['the'; 'cat'; 'sat'], {{1 2 3}; {4 5 6}; {7 8 9}})
T = 3×4 table
Var1 Var2 Var3 Var4 _______ ____ ____ __________ "One" 1 the {1×3 cell} "Two" 2 cat {1×3 cell} "Three" 3 sat {1×3 cell}
T{end+100,1} = missing % add 100 rows
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 = 103×4 table
Var1 Var2 Var3 Var4 _________ ____ ____ ____________ "One" 1 the {1×3 cell } "Two" 2 cat {1×3 cell } "Three" 3 sat {1×3 cell } <missing> 0 {0×0 double} <missing> 0 {0×0 double} <missing> 0 {0×0 double} <missing> 0 {0×0 double} <missing> 0 {0×0 double} <missing> 0 {0×0 double} <missing> 0 {0×0 double} <missing> 0 {0×0 double} <missing> 0 {0×0 double} <missing> 0 {0×0 double} <missing> 0 {0×0 double} <missing> 0 {0×0 double} <missing> 0 {0×0 double}
  8 Comments
Voss
Voss on 8 Jan 2024
"is there a special comment that can be added to that one line to suppress the warning?"
Not a comment, but a command. The warning function can be used to turn on and off individual warning messages by ID. To get the ID you can use the lastwarn function.
Demonstration: First, generate the warning in question:
T = table(["One"; "Two"; "Three"], [1; 2; 3], ['the'; 'cat'; 'sat'], {{1 2 3}; {4 5 6}; {7 8 9}});
T{end+100,1} = missing; % warning is issued
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.
Get the warning ID using lastwarn:
[~,wid] = lastwarn()
wid = 'MATLAB:table:RowsAddedExistingVars'
Turn the warning off:
warning('off',wid)
Verify that it worked by trying to generate the same warning again:
T{end+100,1} = missing; % no warning this time
Now that you know the relevant warning ID, in your code you can turn off the warning before any are generated:
warning('off','MATLAB:table:RowsAddedExistingVars')

Sign in to comment.

Products


Release

R2023a

Community Treasure Hunt

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

Start Hunting!