Copy a data from a file into a structure - matlab

I need help in designing a data structure to store the storm data from the file. I am going to use these field names: code, amount, duration, and intensity. The intensity is the rainfall amount divided by the duration.(what should I do to in order to calculate the intensity?) I loaded the data into the variable "mydata", then copied my data into a vector of structs called "vecdata".
My final vector of structures should have the same number of elements as the number of rows in the data file. Additionally, it should have the 4 fields with the field names I mentioned above.
% Creating an example data file
anum = randi([3,10]);
thedata = [randi([1,350],anum,1),rand(anum,1)*5,rand(anum,1)*15];
save mydata.dat thedata -ascii
clear
% loaded the data using the load function into "mydata":
mydata = load('mydata.dat')
% Tried to copy the data from "mydata" into a vector of structures called "vecdata":
vecdata = [struct('code','amount','duration','intensity')];
This is a very general question. How can I copy the data from the file above? Rows of mydata must match the # of elements in vecdata. How do I check this?

%first of all, calculate the missing intensity
mydata(:,end+1)=mydata(:,3)./mydata(:,2);
%define the fieldnames for your struct
labels={'code','amount','duration','intensity'};
%there is no array2struct, so we convert to cell first and use cell2struct.
cell2struct(num2cell(mydata),labels,2)

Related

Extract structures in a loop

I have a structure ('data'), with 26 fields (A, B, C, D, etc.). Each field contains 1x30 cells (one for each participant), and each cell contains a structure.
I would like to extract all the structures (i.e., one structure per field) corresponding to each participant. That is, I would like to obtain 30 new ‘data’, each with 26 fields, and each field containing 1x1 structure, with the structure corresponding to the participant. I have tried the following code:
data = load('D:\filepath\mydata.mat'); %load file with data. 1x1 struct.
all_fields = fieldnames(data); %store the fields of the structure. 26x1 cell.
forStr = length(all_fields); %26
n_ppts = 30; %total number of participants.
%for each participant, extract the corresponding structure in each field.
for nn = 1:n_ppts
for idx_field = 1:forStr
name_field = all_fields{idx_field};
data2 = data;
data2.(name_field) = data.(name_field){nn};
end
%save the 'data' for each participant. The 'data' should include 26 fields, and 1 structure for each field.
name = ppt_fname(nn); %Generate the new name for saving
savename =string(regexprep(name,'_oldname.set','_newname.mat'));
save(savename, '-struct', 'data');
end
The code doesn’t give any error. However, it doesn’t run as I expected.
‘data2’ still contains 26 fields, but only the last field contains 1 structure corresponding to the participant. The other fields contain 1x30 cell.
I guess it is because every time I run the loop it overwrites the previous fields, leaving only the last field correct. So, I think I might need a temporary variable where to store each iteration of the loop.
I thought to create as the temporary storage for each field
structure = [];
namelist = {‘A’;’B’;’C’;’D’;’E’;’F’;’G’;’H’;’I’;’J’;’K’;’L’;’M’;’N’;’O’;’P’;’Q’;’R’;’S’;’T’;’U’;’V’;’W’;’X’;’Y’;’Z’};
for i = 1:length(namelist)
structure.(namelist{i})={};
end
But cannot figure out how to make it work.
You need to take the line data2 = data; out of the for loops.
Antoine T is right, you always copy the original structure data again to data2 in every loop. That is why it won't get changed (except for the very last step of the loop, where you add a single field name to it.)
Regarding your other problem:
% create empty struct:
S = struct();
% loop
for i = 1:25
% create field name
nm = char( double('A') +i );
% create new field with empty cell.
S.(nm) = {};
end
It is just nice to convert number to chars as fieldnames. Your primary error was that you used the wrong inverted comma to create chars.
A minor flaw though was that you allocated strucutre = [] as an empty matrix rather than as an empty struct

Locate the indexes of rows in Matlab

I have stored in a struct file in matlab a database and the correspondant label files. In order to read my database matrix from the struct into a matrix I am using the following matlab command:
train_data_matrix = (cat(1, train_data.f2));
The size of the train_data struct is 883. However since there are some empty samples in the end the size of the train_data_matrix is 833. My problem is that I have annotation for all the samples. Thereby the size of the annotation is 883x1 How can I remove from the annotation vector the rows that are empty in the database matrix?
You can use isempty to check for missing values and remove them
% Store data in a cell array (preserves missing values)
tmp = {train_data.f2};
% Create a logical array that is TRUE where the missing values are
toremove = cellfun(#isempty, tmp);
% Convert to an array (removes missing values as you've mentioned)
data = cat(1, tmp{:});
% Create an array of annotations (after removing the ones that are missing data)
annotations = cat(1, train_data(~toremove).annotations);

Adding size information of dataset to file name

I have several datasets, called '51.raw' '52.raw'... until '69.raw' and after I run these datasets in my code the size of these datasets changes from 375x91x223 to sizes with varying y-dimensions (i.e. '51.raw' output: 375x45x223; '52.raw' output: 375x50x223, ... different with each dataset).
I want to later save the '.raw' file name with this information (i.e. '51_375x45x223.raw') and also want to use the new dataset size to later reshape the dataset within my code. I have attempted to do this but need help:
for k=51:69
data=reshape(data,[375 91 223]); % from earlier in the code after importing data
% then executes code with dimensions of 'data' chaging to 375x45x223, ...
length=size(data); dimensions.([num2str(k)]) = length; %save size in 'dimensions'.
path=['C:\Example\'];
name= sprintf('%d.raw',k);
write([path name], data);
% 'write' is a function to save the dat in specified path and name (value of k). I don't know how to add the size of the dataset to the name.
Also later I want to reshape the dataset 'data' for this iteration and do a reshape with the new y dimensions value.
i.e. data=reshape(data,[375 new y-dimension 223]);
Your help will be appreciated. Thanks.
You can easily convert your dimensions to a string which will be saved as a file.
% Create a string of the form: dim1xdim2xdim3x...
dims = num2cell(size(data));
dimstr = sprintf('%dx', dims{:});
dimstr = dimstr(1:end-1);
% Append this to your "normal" filename
folder = 'C:\Example\';
filename = fullfile(folder, sprintf('%d_%s.raw', k, dimstr));
write(filename, data);
That being said, it is far better include this dimension information within the file itself rather than relying on the filename.
As a side note, avoid using names of internal functions as variable names such as length, and path. This can potentially result in strange and unexpected behavior in the future.
Update
If you need to parse the filename, you could use textscan to do that:
filename = '1_2x3x4.raw';
ndims = sum(filename == 'x') + 1;
fspec = repmat('%dx', [1 ndims]);
parts = textscan(filename, ['%d_', fspec(1:end-1)]);
% Then load your data
% Now reshape it based on the filename
data = reshape(data, parts{2:end});

Naming Image using index of for loop in each iteration

I am working in MATLAB for my image processing project.
I am using a for loop to generate some kind of image data (size of image varies) with each loop iteration. My problem is how do stop it from overwriting the image in next iteration.
Img(i,j)=data
Ideally I would like it to have
Img_1 = data (for 1st iteration)
Img_2 = data (for 2nd iteration)
Img_3 = data (for 3rd iteration)
and so on...
Is there any way, it can be acheived?
Yes, you can use dynamic field names with structures. I wouldn't recommend using separate variable names because your workspace will become unwieldy. Do something like this:
img_struct = struct(); %// Create empty structure
for ii = 1 : num_iterations
%// Do your processing on data
%...
%...
img_struct.(['Img_' num2str(ii)]) = data; %// After iteration
end
This will create a structure called img_struct where it will have fields that are named Img_1, Img_2, etc. To access a particular data from an iteration... say... iteration 1, do:
data = img_struct.Img_1;
Change the _1 to whatever iteration you choose.
Alternatively, you can use cell arrays... same line of thinking:
%// Create empty cell array
img_cell = cell(num_iterations, 1);
for ii = 1 : num_iterations
%// Do your processing on data
%...
%...
img_cell{ii} = data; %// After iteration
end
Cell arrays are arrays that take on any type per element - or they're non-homogeneous arrays. This means that each element can be whatever you want. As such, because your image data varies in size at each iteration, this will do very nicely. To access data at any iteration, simply do:
data = img_cell{ii};
ii is the index of the iteration you want to access.
If you want to literally obtain what you are asking for, you can use the eval() function, which takes a string as input that it will evaluate as if it were a line of code. Example:
for i=1:3
data=ones(i); % assign data, 'ones(i)' used as dummy for test
eval(['Img_' num2str(i) '=data;'])
end
However, I would recommend using cell arrays {}, or alternatively the struct function that rayryeng both suggested.

Dividing a DataArray and putting names to each Matlab

I have a data array with dimensions 1 x 95125. I want to extract data from it and then give each a name. For example
Station00001=[R{:,1:13}]
Station00002=[R{:,15:27}]
.....
Station06518
The question is, is it possible to create a vector with all the wanted names and then open each data from the data array as above but with all the files with a for loop to its corresponding file
This is what I did but its not working
for i= 1:(length(R)/14)
k=0:((length(R)/14)-1)
A(i)=1+14.*k;
B(i)=A+12;
Stations (i)= [R{:,A(i):B(i)}];
end
Your loop is fine; not sure why you would want to store the A and B indices in an array, though.
numStations = floor(length(R)/14); %# careful: the number of columns in R is not a multiple of 14
Stations = cell(1,numStations);
for i= 1:numStations
fromColumn = (i-1)*14+1;
toColumn = i*14-1;
Stations{i}= [R{:,fromColumn:toColumn}];
end
To access the data from Station 25, use Stations{25}