How to use 'for' loop to string variable ?

I have severals mat files. I have defined these files as a string variable in m file. i can execute the files seperately with a loop.
1st mat file: Battery_Power_280.mat
2nd mat file: Battery_Power_300.mat
3rd mat file: Battery_Power_320.mat
4th mat file: Load_Power_280.mat
If i execute first 3 files its executed successfully. but whenever i add the 4th file(Load_Power_280) with the 'Name' variable its showing this error.
Error using horzcat
Names of fields in structure arrays being concatenated do not match. Concatenation of structure arrays requires that these arrays have the same set of fields.
character length of first 3 files is 17 indibidually. and for the last file is 14. is it the reason ?
My CODE with first 3 files:
Name=["Battery_Power_280","Battery_Power_300","Battery_Power_320"];
N = numel(Name);
C = cell(1,N);
for i = 1:N
C{i} = load(Name{i});
end
Structure = [C{:}]; % its executed successfully.

8 Comments

Looks like each element of C is a struct, and different elements have different sets of fields. Investigate whether what the call to load returns is what is expected.
Stephen23
Stephen23 on 17 Dec 2021
Edited: Stephen23 on 17 Dec 2021
"character length of first 3 files is 17 indibidually. and for the last file is 14. is it the reason ? "
No, the error is completely unrelated to those filenames. The error message tells us that the scalar structures have different field names and therefore cannot be concatenated together into one structure array.
How many variables are saved in each MAT file?
This screen shot tells us that 'time', 'signals' and 'blockName' are fields of the struct 'Data_BatteryPower', which is a field of the struct 'Structure'. Whether the variable 'Structure' or any other variable is in Battery_Power_280.mat we cannot say from this screen shot. Please assign the result of the load call to a variable, like the following (and like it is done in the code):
S = load('Battery_Power_280.mat')
S = load('Load_Power_280.mat')
And please show the output of those two commands.
attached both files(Battery_Power_280.mat and Load_Power_280.mat). could you please check from your end.
Here is the 3rd file for your convenience.
attached a screenshot for your information. is this information enough for you? if not please dont hesitate to reply. thank you.
upper variable result for S, S1 in the lower right side. As both variable you wrote as S, thats why i wrote S and S1.
S = load('Battery_Power_280.mat')
S = struct with fields:
Data_BatteryPower: [1×1 struct]
S = load('Load_Power_280.mat')
S = struct with fields:
Data_LoadPower: [1×1 struct]
These are what get stored as elements of C in the code. One is a struct with one field called 'Data_BatteryPower', and one is a struct with one field called 'Data_LoadPower'. The set of field names is not the same between the two, so they cannot be concatenated in a struct array. This is why the error happens.
One solution is to reference the field 'Data_BatteryPower' for the mat files that have 'Data_BatteryPower' and reference the field 'Data_LoadPower' for the mat files that have 'Data_LoadPower', and concatenate those structs. But the real question is whether these things really need to be concatenated in a struct array at all, or would a cell array of structs - which does allow each element to have a different set of field names - be sufficient? The answer to that question depends on how you use the variable Structure further down in your code.

Sign in to comment.

 Accepted Answer

Assuming that each file contains exactly one variable (itself a structure with the same field names):
T = ["Battery_Power_280","Battery_Power_300","Load_Power_280.mat"];
N = numel(T);
C = cell(1,N);
for k = 1:N
C(k) = struct2cell(load(T{k}));
end
S = [C{:}]
S = 1×3 struct array with fields:
time signals blockName

1 Comment

Great @Stephen. Thanks a lot. i have added few lines to export my expected variable(signal.values)
T = ["Battery_Power_280","Battery_Power_300","Battery_Power_320","Load_Power_280.mat"];
N = numel(T);
C = cell(1,N);
for k = 1:N
C(k) = struct2cell(load(T{k});
end
S = [C{:}];
% Export the signal value
num = numel(S);
D = cell(1,num);
for j=1:num
D{j}=S(j).signals.values(:,1);
end
Matrix=[D{:}];

Sign in to comment.

More Answers (3)

Here's one way to make a struct array, as intended in the code you posted in your question (note that this just uses two of the mat files and explicitly states the field to use (in the variable type)):
Name = ["Battery_Power_280","Load_Power_280"];
type = ["Data_BatteryPower","Data_LoadPower"];
N = numel(Name);
C = cell(1,N);
for i = 1:N
C{i} = subsref(load(Name{i}),substruct('.',type{i}));
end
Structure = [C{:}]
Structure = 1×2 struct array with fields:
time signals blockName

1 Comment

this one also helpful in case of getting type. I appreciate your hard work.

Sign in to comment.

Why you want to make names manually? You can get the files present in the folder using:
matFiles = dir('*.mat') ;
for i = 1:length(matFiles)
load(matFiles(i).name)
end

9 Comments

yahh..its weird, but that is my task.
already i am aware of your code. but anyway i can't apply that. i have to define the variable manually.
Thank you very much for your time.
Define them in a cell array..
applied like this,but showing same error.
Name={'Battery_Power_280','Battery_Power_300','Grid_Power_280'};
N = numel(Name);
C = cell(1,N);
for i = 1:N
C{i} = load(Name{i});
end
Structure = [C{:}];
"applied like this,but showing same error"
Of course you will get the same error, because the error has absolutely nothing to do with the filenames.
As @Stephen said there is no error with file names..what error you are getting exactly?
Arif Hoq
Arif Hoq on 17 Dec 2021
Edited: Arif Hoq on 17 Dec 2021
as wirtten earlier,
Error using horzcat
Names of fields in structure arrays being concatenated do not match. Concatenation of structure arrays requires that these arrays have the same set of fields.
i have uploaded the mat files. could you please check?
So problem is in C...one needs to check C to rectify the error. What contents mat files have? All mat files have same kind of data?
all mat files have same types of data.please check the latest screenshot. Even you open the mat files from your end. I appreciate your hard work.
Stephen23
Stephen23 on 17 Dec 2021
Edited: Stephen23 on 17 Dec 2021
"all mat files have same types of data"
No, the variable names are different.
When you LOAD into a structure those variable names are given as different fieldnames (of the scalar structures inside the cell array). Scalar structures of different fieldnames cannot be concatenated together.

Sign in to comment.

trying something new. want to export all mat files as@KSSV suggested. applied this code:
files = dir('*.mat') ;
for k = 1:length(files)
load(files(k).name);
end
20 mat files exist in my folder. but after execution it shows only 4 mat files data(Actually got these 4 mat files from simulink. after simulation i have renmaed the files like "Battery_Power_280","Battery_Power_300","Battery_Power_320","Grid_Power_280","Grid_Power_300" so on...).
actual simulated mat files name: "Data_BatteryPower,Data_GridPower,Data_LoadPower,Data_PVPower"
Is it possible to export all data from these 20 mat files ? please check the screenshot for further information.

10 Comments

If you load a mat file without assigning the output of the load function to a variable, the contents of the mat file get loaded as variables into your workspace. If you were to then load another mat file the same way with variables of the same name in it, those would overwrite what was loaded from the previous mat file.
This is what is happening here. You get four struct variables at the end of the loop because there are four unique variable names across all 20 mat files. Each time you load a new mat file, the variable in the workspace with the same name as the variable in the mat file is overwritten (if it already exists).
To avoid this, you must assign the result of load to something: a cell array maybe. Like this:
files = dir('*.mat') ;
C = cell(1,length(files));
for k = 1:length(files)
C{k} = load(files(k).name);
end
This keeps them all nice and separate and not overwriting each other. Then you can export whatever you want or do whatever you want with them. For examples of code, see previous answers and comments in this thread.
nice explanation. this reason i have thought before, but not much perfect as you said. now i can export my expected variable. but possibly, i can not export all the data at once as number of fields does not match each other.
by the way, i think cell array of line 4 should be C{k} instead of C{i}.
Good catch! I will correct it.
You can still export it all as a cell array.
An alternative to a cell array is to utilise the already-existing structure array returned by DIR:
S = dir('*.mat');
for k = 1:numel(S)
S(k).data = load(S(k).name);
end
This has the benefit that the filenames and file data are stored in the same array (i.e. can be sorted together).
Unable to export data after certain mat files. its because of different fields. first 5 mat files have similar field that i can export. then matlab showing error...
Subscripted assignment between dissimilar structures.
Error in testing9 (line 10)
Matrix(j)=C{1,j};
Used this code:
files = dir('*.mat') ;
C = cell(1,length(files));
for k = 1:length(files)
C{k} = load(files(k).name);
end
for j=1:length(files)
Matrix(j)=C{1,j};
end
first 5 mat files has 1 fields with struct
>> C{1,1}
ans =
struct with fields:
Data_BatteryPower: [1×1 struct]
but 6th mat file has 3 fields with struct that is dissimilar from above 5 mat files
>> C{1,6}
ans =
struct with fields:
ave_bat_summ_280: [1×56 double]
max_bat_summ_280: [1×56 double]
total_bat_summ_280: [1×56 double]
short but very powerful syntax @Stephen.
1. then,how to export these data instead of manual coding?
(Data1= S(1).data )
2. still i want to export the data from the cell array as Benjamin suggested. but,getting some error.
Stephen23
Stephen23 on 22 Dec 2021
Edited: Stephen23 on 22 Dec 2021
" then,how to export these data instead of manual coding?"
Do NOT do that.
Hiding pseudo-indices in the variable names makes your code slow, complex, inefficient, and difficult to debug:
The simple and efficient approach is to access the data using indexing. Indexing is what you should use.
You are trying to hide pseudo-indices in the variable names, which make your data difficult and very inefficient to work with. Is there any reason why you cannot use actual indices to access your data?
noted your suggestion.
I have 20 mat files right now in my folder. it will be more and more later. using actual indices is lengthy process i guess.
"using actual indices is lengthy process i guess. "
No, using actual indices is the simplest approach. It makes it trivial and very efficient to write a loop to process your data, something that would be complex and very inefficient using your approach.
Why do you think that it would be "lengthy"? (when the reality is that it would be simpler and easier for you)
its simpler and easier,i admit that. i will follow your hints.

Sign in to comment.

Categories

Asked:

on 17 Dec 2021

Commented:

on 22 Dec 2021

Community Treasure Hunt

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

Start Hunting!