Borrar filtros
Borrar filtros

MATLAB not indexing table with correct data type, how to specify data type when indexing table?

8 visualizaciones (últimos 30 días)
I wrote a script that takes in an excel table using the "readtable" command.
inputTable = readtable(completeTableFilePath,'Sheet',sheetChoiceFileName,'TextType','string');
This, to my knowledge, should import all the cells of the excel file as strings. One part of the excel file is a column that has hex numbers (they cold be just "92" or "13C" etc...).
I had a really long excel table (around 300 lines) that had this column of hex numbers. I tried the program with a smaller table, maybe only 8 lines, and now it is having issues, particularly in the hex column.
The code:
% I just added these for testing (the idName)
idName = upper(inputTable{currentRowNumber,'ID'});
idName
if upper(inputTable{currentRowNumber,'ID'}) ~= "TBD"
if upper(inputTable{currentRowNumber,'ID'}) ~= recurringID
recurringID = upper(inputTable{currentRowNumber,'ID'});
messageIDDecimal = hex2dec(recurringID);
end
end
As I said, I changed nothing about this between runs, it works perfectly with the large table and it does not work with the smaller table. When I try to run it with the smaller table (which is just the larger table with a lot of the rows chopped off) I get idName as a "double" data type.
I figured I could fix this, by instead of relying on MATLAB to have the correct data type (which it should anyways because I specified so earlier!) I force the data type of strings using string(...).
% idName for testing
idName = upper(string(inputTable{currentRowNumber,'ID'}));
idName
if upper(string(inputTable{currentRowNumber,'ID'})) ~= "TBD"
if upper(string(inputTable{currentRowNumber,'ID'})) ~= recurringID
recurringID = upper(string(inputTable{currentRowNumber,'ID'}));
messageIDDecimal = hex2dec(recurringID);
end
end
I ran the above code on the smaller table and got the error: <missing> string element not supported; error on line with the hex2dec. idName shows up as <missing>.
I changed the code again to show the raw table indexing:
% idName for testing
idName = upper(string(inputTable{currentRowNumber,'ID'}));
idName
idTest = inputTable{currentRowNumber,'ID'};
idTest
if upper(string(inputTable{currentRowNumber,'ID'})) ~= "TBD"
if upper(string(inputTable{currentRowNumber,'ID'})) ~= recurringID
recurringID = upper(string(inputTable{currentRowNumber,'ID'}));
messageIDDecimal = hex2dec(recurringID);
end
end
idTest was coming up as the double data type, until the final go. idName was <missing> and idTest was "NaN". To my knowledge, "NaN" is "Not a Number". It is giving an error because it's trying to input a hex number as a regular double data type. I cannot find a way to fix this. I already specified that the table is to be imported as strings. I cannot cast to this, because its not just holding the data, but being the wrong type. It is throwing an error and not holding the data at all.
There is nothing I can do, unless there is some way to make MATLAB only import as a specific data type. I am having a lot of issues, because MATLAB assumes data types. Maybe coming from C just has me think differently. I can see how it can be useful, but the fact that there is no way around it (that I know of), makes it not useful.
I ran the script with "idName" and "idTest" on the larget excel table. It properly imported them as strings. I was able to index and both idTest and idName showed as strings, even the hex numbers that only had the regular 0-9 numbers. So it is not the code. It is just MATLAB sometimes deciding to import as strings and sometimes to not.

Respuesta aceptada

Voss
Voss el 19 de Jun. de 2024
Setting 'TextType' is for specifying whether the data readtable imports as text should be returned as string arrays or character vectors. It does not set the imported data type in general, as you have found. For instance, if readtable determines that some data is numeric, then 'TextType' has no effect on that data since it is not text.
To specify imported data types you can use detectImportOptions and setvartype.
Example:
% the file's contents
type('test.csv')
ID 92 2A
% the problem
T = readtable('test.csv')
T = 2x1 table
ID ___ 92 NaN
% a solution
opts = detectImportOptions('test.csv'); % default import options for the file
opts = setvartype(opts,'ID','string'); % set 'ID' variable to be of type 'string'
T = readtable('test.csv',opts) % readtable with the new options
T = 2x1 table
ID ____ "92" "2A"
  11 comentarios
Kealan
Kealan el 20 de Jun. de 2024
So, I was able to get it to work. I had to use:
opts = detectImportOptions(completeTableFilePath,'Sheet',sheetChoiceFileName);
opts = setvartype(opts,'ID','string');
% ... a list of the same type of thing as above with different names and
% data types
opts = setvartype(opts,'Unit','string');
inputTable = readtable(completeTableFilePath,opts,'Sheet',sheetChoiceFileName);
I had to get rid of the 'TextType', 'string' option. It said invalid parameter or something of the like, but if I can force the data type now, then I do not need to worry about that.
This works great!! Thank you all who were involved!!
dpb
dpb el 20 de Jun. de 2024
",,,I cannot do those in the same line, but I can do one line per data type"
Yes, per setvartype documentation, the type argument must be a scalar. A seemingly useful enhancement would be to let both selection and type be cellstr or string arrays with a 1:1 correspondence.
There's also a feature vartype with a table that allows you to index by the current type and convertvars will let you then change by that indexing method. Keep poking at the doc and don't stop reading at the first line; study it in depth; there's a lot hidden in the bowels a cursory glance won't tell you.

Iniciar sesión para comentar.

Más respuestas (1)

dpb
dpb el 20 de Jun. de 2024
Editada: dpb el 21 de Jun. de 2024
There are even more alternatives available with setvaropts including identifying the column(s) as hex. This adds the limitation that have to use an integer type, but that can then be cast to a double.
c=[[{'ID1'};{'0x92'};{'0x2A'}], [{'ID2'};{'92'};{'2A'}]];
fn='test.csv';
writecell(c,fn)
type test.csv
ID1,ID2 0x92,92 0x2A,2A
opt=detectImportOptions(fn);
opt=setvaropts(opt,'ID2','NumberSystem','hex','Type','int32');
opt =
DelimitedTextImportOptions with properties: Format Properties: Delimiter: {','} Whitespace: '\b\t ' LineEnding: {'\n' '\r' '\r\n'} CommentStyle: {} ConsecutiveDelimitersRule: 'split' LeadingDelimitersRule: 'keep' TrailingDelimitersRule: 'ignore' EmptyLineRule: 'skip' Encoding: 'UTF-8' Replacement Properties: MissingRule: 'fill' ImportErrorRule: 'fill' ExtraColumnsRule: 'addvars' Variable Import Properties: Set types by name using setvartype VariableNames: {'ID1', 'ID2'} VariableTypes: {'auto', 'int32'} SelectedVariableNames: {'ID1', 'ID2'} VariableOptions: [1-by-2 matlab.io.VariableImportOptions] Access VariableOptions sub-properties using setvaropts/getvaropts VariableNamingRule: 'modify' Location Properties: DataLines: [2 Inf] VariableNamesLine: 1 RowNamesColumn: 0 VariableUnitsLine: 0 VariableDescriptionsLine: 0 To display a preview of the table, use preview
tT=readtable(fn,opt,'ReadVariableNames',1)
tT = 2x2 table
ID1 ID2 ___ ___ 146 146 42 42

Productos


Versión

R2023b

Community Treasure Hunt

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

Start Hunting!

Translated by