Unrecognized Field name in struct error, even though same Fieldname clearly in struct

I am writing a GUI, that automatically imports data from a table and sorts it into a struct with fields. I created a cell with strings "VN" (VariableNames), with data_in beeing a 401x6 table in this example.
app.VN = app.data_in.Properties.VariableNames;
% Manually outputting VN into workspace shows:
VN=app.VN
VN =
1×6 cell array
Columns 1 through 5
{'x1_1_1RadVorneR…'} {'x1_1_1RadVorneR…'} {'x2_1_1Sitzschiene'} {'x2_1_1Sitzschie…'} {'x3_1_1Sitzkissen'}
Column 6
{'x3_1_1Sitzkisse…'}
so i can later open each field in my struct "data" by calling it like this for example:
app.data.(app.VN{i})
My Problem: I want to compare different Fields with eachother in an if statement, with "i" beeing used from a for function:
for i=2:width(app.data_in)
if app.data.(app.VN{1}) == app.data.(app.VN{i})
%...
But i get the warning message "Unrecognized field name "x1_1_1RadVorneRechts"." in the line of the if statement.
If I manually output the struct "data" into the workspace, one line before the aforementioned "for" function starts, i get this output, clearly showing, that the field name exists:
data=app.data
data =
struct with fields:
x1_1_1RadVorneRechts: [401×1 double]
x1_1_1RadVorneRechts_2: [401×1 double]
x2_1_1Sitzschiene: [401×1 double]
x2_1_1Sitzschiene_2: [401×1 double]
x3_1_1Sitzkissen: [401×1 double]
x3_1_1Sitzkissen_2: [401×1 double]
Why do i get this error message and how do i resolve it? It is critical for the rest of the GUI, that i can compare different field values with eachother.

9 commentaires

How do you convert app.data_in (a table) to app.data (a structure)? And why do you convert it to a structure rather than leaving it as a table?
Hi Chris, i converted it because i copied some 200 lines of codes from an older program in the later parts, that work with a cell (f.e. fill dropdown menues, axis labels etc).
Here is how the table is converted to a structure (this one produces the mistake) (the delimiter swap shouldn't matter);
for i = 1 : length(app.VN)
app.data.(app.VN{i}) = str2double(strrep(app.data_in.(app.VN{i})(1:end),',','.'));
end
Next question - how are you loading your table into app.data_in? I'm curious how you are creating numbers where comma is the decimal separator, but your code needs it to be periods. Or why your numbers are coming in as strings.
If you are loading it from a file, look into readtable or readmatrix.
readtable(filename,"DecimalSeparator",",")
Note that a comma may be the default delimiter. If you numbers are coming in as 2 separate number, specifiy the delimiter.
As my program works with importing different types of data (mainly .csv and .txt, with different delimiters, i prefer to first import it with readtable, and then change delimiters if necessary. My import looks like this, with app.path_n and app.filename apprehended by uigetfile.
[app.file_list, app.path_n] = uigetfile('*.*', 'Multiselect', 'on');
app.data_in = readtable([app.path_n app.filename]);
In some cases, depending on the file name, i change the import options, here is an example:
if contains(app.filename, '.csv') == true
opts=detectImportOptions([app.path_n app.filename]);
opts.VariableNamesLine=1;
opts.VariableDescriptionsLine=3;
opts.DataLine=4;
%
app.data_in = readtable([app.path_n app.filename],opts);
end
Shortly after that i create the aforementioned struct "data".
Edit: The imported data is highly variable, though mostly from swinging systems with multiple accelleration sensors. The GUI aims to be an allround, fast, automatic analysis tool for different types of measurements for vehicle suspension systems under different loads.
If it's working, you don't need to change it. I'm searching for what may be causing your issue. Based on everything you've shared, I cannot duplicate the error message. Have you left something out?
x1_1_1RadVorneRechts = rand(401,1);
x1_1_1RadVorneRechts_2 = rand(401,1);
x2_1_1Sitzschiene = rand(401,1);
x2_1_1Sitzschiene_2 = rand(401,1);
x3_1_1Sitzkissen = rand(401,1);
app.data_in = table(x1_1_1RadVorneRechts,x1_1_1RadVorneRechts_2,x2_1_1Sitzschiene,x2_1_1Sitzschiene_2,x3_1_1Sitzkissen)
app = struct with fields:
data_in: [401×5 table]
app.VN = app.data_in.Properties.VariableNames
app = struct with fields:
data_in: [401×5 table] VN: {'x1_1_1RadVorneRechts' 'x1_1_1RadVorneRechts_2' 'x2_1_1Sitzschiene' 'x2_1_1Sitzschiene_2' 'x3_1_1Sitzkissen'}
for i = 1 : length(app.VN)
% app.data.(app.VN{i}) = str2double(strrep(app.data_in.(app.VN{i})(1:end),',','.'));
app.data.(app.VN{i}) = app.data_in.(app.VN{i});
end
for i=2:width(app.data_in)
if app.data.(app.VN{1}) == app.data.(app.VN{i})
% Since I use random numbers, this will never be true
end
end
app.data
ans = struct with fields:
x1_1_1RadVorneRechts: [401×1 double] x1_1_1RadVorneRechts_2: [401×1 double] x2_1_1Sitzschiene: [401×1 double] x2_1_1Sitzschiene_2: [401×1 double] x3_1_1Sitzkissen: [401×1 double]
Can you share the full text of the error message (all the red text).
Just a note about your comparison in your if statement. It will only be true if every elementwise comparison is true (vector on the left is exactly the same as the vector on the right). Is that what you wanted? You can make that more explicit by using all:
if all(app.data.(app.VN{1}) == app.data.(app.VN{i}))
This is the entire code after my import function (just a standard uigetfile), up to the error in the last line:
app.VN=[];
app.data={};
if contains(app.filename, '.csv') == true
opts=detectImportOptions([app.path_n app.filename]);
opts.VariableNamesLine=1;
opts.VariableDescriptionsLine=3;
opts.DataLine=4;
app.data_in = readtable([app.path_n app.filename],opts);
%
for j=1:width(app.data_in)
if contains(app.data_in.Properties.VariableNames{j},'Var')==1
app.data_in.Properties.VariableNames{j}=strcat(app.data_in.Properties.VariableNames{j-1},'_2');
end
end
%
app.VN = app.data_in.Properties.VariableNames;
%
for i = 1 : length(app.VN)
app.data.(app.VN{i}) = str2double(strrep(app.data_in.(app.VN{i})(1:end),',','.'));
end
data_in=app.data_in
data=app.data
VN=app.VN
%
% These import options do not produce that error msg! So i commented them out.
% elseif contains(app.filename, '.txt')==true
% % opts=detectImportOptions([app.path_n app.filename]);
% app.data_in = readtable([app.path_n app.filename]);
% %
% app.VN = app.data_in.Properties.VariableNames;
% app.data=app.data_in;
% %
% else
% app.data_in = readtable([app.path_n app.filename]);
% app.VN = app.data_in.Properties.VariableNames;
% app.data=app.data_in;
% end
% Dazu Feld 1 mit anderen Feldern vergleichen:
for i=2:width(app.data_in)
if app.data.(app.VN{1}) == app.data.(app.VN{i})
app.data=rmfield(app.data,app.VN{i});
%[...]
The complete error Msg from the Matlab Workspace:
Unrecognized field name "x1_1_1RadVorneRechts".
Error in SS14/DateiAuswahl2 (line 344)
if app.data.(app.VN{1}) == app.data.(app.VN{i})
Error in SS14/import2 (line 288)
app.DateiAuswahl2; %This is the name of the callback function with the code above
Error using matlab.ui.control.internal.controller.ComponentController/executeUserCallback (line 410)
Error while evaluating Button PrivateButtonPushedFcn.
And yes, it is intended, that the if statement compares every element of those 2 vectors. The measured data usually has multiple rows representing the time. If i have bigger data with f.e. 16 sensors, and it produces 16 time vectors along those, the rest of the GUI would be very ugly and confusing, as i have f.e. a Dropdown item for every Variable etc.
As a debugging step, just below the Dazu Feld 1 mit anderen comment, please add the following tests:
datafields = fieldnames(app.data)
missing = find(~ismember(app.VN, datafields));
if ~isempty(missing)
fprintf('Some VN fields do not match. Existing fields are\n');
existfields = strjoin(compose("|%s|", datafields), ', ');
fprintf('%s\n', existfields);
fprintf('VN data fields not found in app.data are:\n');
missfields = strjoin(compose("|%s|", app.VN{missing}), ', ');
fprintf('%s\n', missfields);
miss1 = app.VN{missing(1)};
fprintf('character codes for |%s| are: %s\n', miss1, cell2mat(double(miss1)));
else
fprintf('All VN data fields found\n');
end
Displaying the character codes for the first missing one might possibly help to see some subtle difference such as a hidden character like newline.
Did that, i just paste the entire workspace result here:
datafields =
6×1 cell array
{'x1_1_1RadVorneRechts' }
{'x1_1_1RadVorneRechts_2'}
{'x2_1_1Sitzschiene' }
{'x2_1_1Sitzschiene_2' }
{'x3_1_1Sitzkissen' }
{'x3_1_1Sitzkissen_2' }
All VN data fields found
% Rest was in red letters, as per usual for an error msg
Unrecognized field name "x1_1_1RadVorneRechts".
Error in SS14/DateiAuswahl2 (line 355)
if app.data.(app.VN{1}) == app.data.(app.VN{i})
Error in SS14/import2 (line 288)
app.DateiAuswahl2;
Error using matlab.ui.control.internal.controller.ComponentController/executeUserCallback (line 410)
Error while evaluating Button PrivateButtonPushedFcn.
Janik Ruge
Janik Ruge le 21 Août 2021
Modifié(e) : Janik Ruge le 21 Août 2021
I found my mistake. Later during the if queue i rename the field with renameStructField by mistake. Before, i had that command after the for queue and when restructuring some code i misplaced it. I made the mistake of not searching the failure later during the "for" queue.
This caused the program to rename the field, but not update VN, thus when continuing the "for" queue, the first field of "data" was renamed, while VN wasn't. I now update VN after renaming the Field during the for queue, which fixed the problem.
Thanks for the help anyways! Would not have found it without that precise help.

Connectez-vous pour commenter.

Réponses (0)

Catégories

Produits

Version

R2021a

Question posée :

le 20 Août 2021

Modifié(e) :

le 21 Août 2021

Community Treasure Hunt

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

Start Hunting!

Translated by