I need to rename a bunch of fields in a structure by basically changing the prefix on it.
e.g.
MyStruct.your_firstfield
MyStruct.your_secondfield
MyStruct.your_thirdfield
MyStruct.your_forthfield
%etc....
to
MyStruct.my_firstfield
MyStruct.my_secondfield
MyStruct.my_thirdfield
MyStruct.my_forthfield
%etc...
without typing each one out...since there are many and may grow.
Thanks!
You can do this by dynamically generating field names for the output struct.
% Example input
MyStruct = struct('your_firstfield', 1, 'your_secondfield', 2, 'your_thirdfield', 3 );
% Get a cell array of MyStruct's field names
fields = fieldnames(MyStruct);
% Create an empty struct
temp = struct;
% Loop through and assign each field of new struct after doing string
% replacement. You may need more complicated (regexp) string replacement
% if field names are not simple prefixes
for ii = 1 : length(fields)
temp.(strrep(fields{ii}, 'your', 'my')) = MyStruct.(fields{ii});
end
% Replace original struct
MyStruct = temp;
Related
My goal is to load some files listed in the table, extract the data, and save the results as a variable of the first file name. The lists in the table are user-input characters, which represent the names of the files that will be loaded soon. I'll give you an example because you may not understand what I mean. When A,B,C (strings) are listed in the table, my code will find where they are located(eg A.txt) and load their data. After the data has been collected from them, the results are saved in the name of the table like this : A(variable)= result_data(:4). Here is my code. please let me know the wrong place. (Note that table is nx1 cell array using uitable.)
function pushbutton1_Callback(hObject, eventdata, handles)
data = get(handles.uitable,'data'); % get strings in table
for i = 1:size(data(:,1)) % count the #strings
fid = fopen([ data(i),'.csv' ]); %load the data and extract what I need
...
fclose(fid);
data(i) = result(row_1:row_2 , 4) % this is the result_data
% data(i) is variable string, so I am not sure whether to use the eval function.
end
Without having your table to debug further here is my suggestions. data is probably a cell array since you are pulling it from a uitable as below.
data = get(handles.uitable,'data'); % get strings in table
So this line should error:
fid = fopen([ data(i),'.csv' ]);
Change it to this:
fid = fopen([ data{i},'.csv' ]);
or this:
fid = fopen([ char(data(i)),'.csv' ]);
When saving your results to the variable name which matches your string I would suggesting using a structure with dynamic field names instead of a bare variable ... otherwise you will probably have to use eval which should be avoided.
So this (which isn't what you asked for):
data(i) = result(row_1:row_2 , 4) % this is the result_data
Should become:
outData.(data{i}) = result(row_1:row_2 , 4) % this is the result_data
If data is a cell array like you said containing {'A','B','C',...}
Then outData would be of the form below and contain each results.
outData.A
outData.B
outData.C
I am trying to assign the field values of structure in loop.
Structure declaration with empty values:
result_struct = struct('a',{},'b',{},'c',{},'d',{})
I am assigning values in loop like that:
% assume a, b, c, d are variables in my workspace
% field names match with the variable names
for index=1:n
% some computation and store results in variables (a-d)
result_struct(index).a = a;
result_struct(index).b = b;
result_struct(index).c = c;
result_struct(index).d = d;
end
How can I assign the values to the fields using another loop? Like that:
for fname = fieldnames(result_struct)'
result_struct(index).fname = fname; % field names and variable names match
end
You need to use dynamic field names to assign to the struct (the leff-hand side). For the right hand side you could use eval but that is dangerous, so it's better to save your variable fname to a file and then load it back in as a struct prior to accessing fname, again using dynamic field names.
names = fieldnames(result_struct);
for k = 1:numel(names)
% Save variable to a file
save('tmp.mat', names{k});
% Load it back into a struct
tmp = load('tmp.mat', names{k});
result_struct(index).(names{k}) = tmp.(names{k});
end
Alternately, you can use the save and load to just transform the entire thing into a struct without having to loop through the fields.
fields = fieldnames(result_struct);
% Save all relevant variables to a file
save('tmp.mat', fields{:});
% Load it back into the result_struct
result_struct(index) = orderfields(load('tmp.mat'), fields);
I have a long list of variables in my workspace.
First, I'm finding the potential variables I could be interested in using the who function. Next, I'd like to loop through this list to find the size of each variable, however who outputs only the name of the variables as a string.
How could I use this list to refer to the values of the variables, rather than just the name?
Thank you,
list = who('*time*')
list =
'time'
'time_1'
'time_2'
for i = 1:size(list,1);
len(i,1) = length(list(i))
end
len =
1
1
1
If you want details about the variables, you can use whos instead which will return a struct that contains (among other things) the dimensions (size) and storage size (bytes).
As far as getting the value, you could use eval but this is not recommended and you should instead consider using cell arrays or structs with dynamic field names rather than dynamic variable names.
S = whos('*time*');
for k = 1:numel(S)
disp(S(k).name)
disp(S(k).bytes)
disp(S(k).size)
% The number of elements
len(k) = prod(S(k).size);
% You CAN get the value this way (not recommended)
value = eval(S(k).name);
end
#Suever nicely explained the straightforward way to get this information. As I noted in a comment, I suggest that you take a step back, and don't generate those dynamically named variables to begin with.
You can access structs dynamically, without having to resort to the slow and unsafe eval:
timestruc.field = time;
timestruc.('field1') = time_1;
fname = 'field2';
timestruc.(fname) = time_2;
The above three assignments are all valid for a struct, and so you can address the fields of a single data struct by generating the field strings dynamically. The only constraint is that field names have to be valid variable names, so the first character of the field has to be a letter.
But here's a quick way out of the trap you got yourself into: save your workspace (well, the relevant part) in a .mat file, and read it back in. You can do this in a way that will give you a struct with fields that are exactly your variable names:
time = 1;
time_1 = 2;
time_2 = rand(4);
save('tmp.mat','time*'); % or just save('tmp.mat')
S = load('tmp.mat');
afterwards S will be a struct, each field will correspond to a variable you saved into 'tmp.mat':
>> S
S =
time: 1
time_1: 2
time_2: [4x4 double]
An example writing variables from workspace to csv files:
clear;
% Writing variables of myfile.mat to csv files
load('myfile.mat');
allvars = who;
for i=1:length(allvars)
varname = strjoin(allvars(i));
evalstr = strcat('csvwrite(', char(39), varname, '.csv', char(39), ', ', varname, ')');
eval(evalstr);
end
I have a large amount of .csv files from my experiments (200+) and previously I have been reading them in seperately and also for later steps in my data handling this is tedious work.
co_15 = csvread('CO_15K.csv',5,0);
co_25 = csvread('CO_25K.csv',5,0);
co2_15 = csvread('CO2_15K.csv',5,0);
co2_80 = csvread('CO2_80K.csv',5,0);
h2o_15 = csvread('H2O_15K.csv',1,0);
etc.....
So I want to make a cell at the beginning of my code looking like this and then a for loop that just reads them automatically.
input = {'co_15' 5;'co_25' 5;...
'co2_15' 5; 'co2_80' 5;...
'h2o_15' 1; 'h2o_140' 1;...
'methanol_15' 5;'methanol_120' 5;'methanol_140' 5;...
'ethanol_15' 5;'ethanol_80' 1;'ethanol_140' 5;...
'co2_ethanol_15' 5 ;'co2_ethanol_80' 5;...
'h2o_ethanol_15' 1 ;'h2o_ethanol_140' 1;...
'methanol_ethanol_15' 5;'methanol_ethanol_120' 5;'methanol_ethanol_140' 5};
for n = 1:size(input,1)
input{n,1} = csvread(strcat(input{n,1},'k.csv'),input{n,2},0);
end
The cell in this code is 19 rows and 2 columns, the rows are all the files and the columns will contain the parameters to handle the data. Now the problem I can't find a solution for is that my first column is a string name and I want that string name to be the name of the variable where csvread writes its data to but the way I set it up now it just overwrites the string in the first column of the cell with the csv data. To be extra clear I want my matlab workspace to have variables with string names in the first column containing the data of my csv files. How do I solve this?
You don't actually want to do this. Even the Mathworks will tell you not to do this. If you are trying to use variable names to keep track of related data like this, there is always a better data structure to hold your data.
One way would be to have a cell array
data = cell(size(input(:,1)));
for n = 1:size(input,1)
data{n} = csvread(strcat(input{n,1},'k.csv'),input{n,2},0);
end
Another good option is to use a struct. You could have a single struct with dynamic field names that correspond to your data.
data = struct();
for n = 1:size(input,1)
data.(input{n,1}) = csvread(strcat(input{n,1},'k.csv'),input{n,2},0);
end
Or actually create an array of structs and hold both the name and the data within the struct.
for n = 1:size(input, 1)
data(n).name = input{n,1};
data(n).data = csvread(strcat(input{n,1},'k.csv'),input{n,2},0);
end
If you absolutly insist on doing this (again, it's is very much not recommended), then you could do it using eval:
for n = 1:size(input, 1)
data = csvread(strcat(input{n,1},'k.csv'),input{n,2},0);
eval([input{n, 1}, '= data;']);
end
I am trying to assign valuable, which is number and given by for loop, to the name of structure field. For example, I would like to do as following,
A.bx, where A is name of structure(= char), b is part of field name ( = char) and x is valuable given by for loop. A and b is fixed or predefined.
Any comment is appreciated !
genvarname(str,list) generates a valid variable name in str [a string] in which at each iteration value in str is different from the exclusion list
And fieldname(S) returns a list of all the names of the field already in the structure S (use it to create a exclusion list)
Here is a code for what you want:
A = struct ();
for i = 1:5
A.(genvarname ('b', fieldnames (A))) = i;
end
Read about 1. genvarname(str,list) 2. fieldnames(S)
You can name you struct fields using simple sprintf
A = struct()
for ii = 1:10
fn = sprintf('b%d', ii );
A.(fn) = ii; % use the struct
end
I tend to agree with sebastian that suggested using arrays or cells over this type of field naming. In addition to cells and arrays you might find containers.Map to be very versatile and useful.