Looping through structure in matlab to sort - matlab

I have a structure with 7 fields. In each cell of the 7th field there is a date. I need a nested loop to sort through those dates and if any of those dates do not exist in the 2nd field of the same structure I would like to take that information (from all 7 fields) and create a new structure containing only the iterations that has dates in the 2nd field but not the 7th. The code that I have so far is:
for i=1:12 %number of dates in the 7th field
for j=1:length(files_cdf) %number of dates in the 2nd field
y(i,j)=isequal(files_cdf(j).date,files_cdf(i).deletables);
if isequal(y(i,j),0)
cdf(j)=files_cdf(j);
end
end
end
But it copies my entire original structure into the new structure without removing the unwanted information. Any help would be greatly appreciated!

I think the loops can be eliminated through some vectorization via bsxfun assuming the elements are scalars of type datetime:
% Convert to double
second = datenum([files_cdf(:).date].');
seventh = datenum([files_cdf(:).deletables]);
%
% Make logical mask
mask = all(bsxfun(#ne,second,seventh),2)
%
% Mask struct array
cdf = files_cdf(mask);

Related

Display all predictions and their percentages in the title of a figure

Im working on a project in deep learning. I have two variables for storing predictions and their percentages.
This is done using a for loop for every image in a cell array C. Both predictions and percentages are stored in separate column vectors which Ill need for later use
for i=1:size(C)
img=im2uint8(C{i});
img2=imresize(img,[224 224]);
[prediction,pred_val] = classify(n_net,img2)
predictions(i,:)=prediction;
pred_vals(i,:)=pred_val;
figure
imshow(img2)
title(sprintf("%s %s",[labels,num2str(100*pravdepodobnost_predikciesnimky(i,:))]));
end
Now, I want to display all of the predictions and percentages, so lets say the network predicts that image consists of 80%ocean and 20% people, so the title in the figure displays both predictions not just the dominant one. Which is the best way to do this?
Edit: here is a sample for clarification (the titles and labels are in my native language):
labels=string(categories(scenes_training.Labels)') %creates 1x2 string array
labels =
"Pobrežie" "Ulica"
After one iteration from the for loop above I get this:
prediction = categorical
Ulica
pred_vals = 1×2 single row vector
0.0046 0.9954
And (after modification) a figure
So my goal is to write the title like this:
Pobrežie 0.45644 %; Ulica 99.5436 %
Given the variables described above then you can use sprintf to do what you want.
% Use the dummy data from above
labels = ["Pobrežie", "Ulica"];
pred_vals = [0.0046, 0.9954];
% now format a string to use as a title
img_title=sprintf("%s %s%%; ", [labels', num2str(100*pred_vals')]');
%img_title now equals "Pobrežie 0.46%; Ulica 99.54%; "
Basically sprintf will cycle through all values it is supplied with, repeating the string format until it is done. You can use this to list the contents of a matrix of data. Putting the data in a matrix and transposing it is just a way of interleaving the names and the values.
The nested transposing in the sprintf input arguments is just to persuade matlab to deal correctly with the different value types - it is a little hacky but then MATLAB often is. If I can find a nicer way then I'll update the answer.
If you don't want the final "; " at the end of the string, then you can trim that off with a subsiquent step.

Splitting non-continuous sized matrix in vectors

I'm writing an piece of software within Matlab. Here, the user can define a dimension say 3.
This dimension is subsequently the number of iterations of a for loop. Within this loop, I construct a matrix to store the results which are generated during every iteration. So, the data of every iteration is stored in a row of a matrix.
Therefore, the size of the matrix depends on the size of the loop and thus the user input.
Now, I want to separate each row of this matrix (cl_matrix) and create separate vectors for every row automatically. How would one go on about? I am stuck here...
So far I have:
Angle = [1 7 15];
for i = 1:length(Angle)
%% do some calculations here %%
cl_matrix(i,:) = A.data(:,7);
end
I want to automate this based on the length of Angle:
length(Angle)
cl_1 = cl_matrix(1,:);
cl_7 = cl_matrix(2,:);
cl_15= cl_matrix(3,:);
Thanks!
The only way to dynamically generate in the workspace variables variables whos name is built by aggregating string and numeric values (as in your question) is to use the eval function.
Nevertheless, eval is only one character far from "evil", seductive as it is and dangerous as it is as well.
A possible compromise between directly working with the cl_matrix and generating the set of array cl_1, cl_7 and cl_15 could be creating a structure whos fields are dynamically generated.
You can actually generate a struct whos field are cl_1, cl_7 and cl_15 this way:
cl_struct.(['cl_' num2str(Angle(i))])=cl_matrix(i,:)
(you might notice the field name, e. g. cl_1, is generated in the same way you could generate it by using eval).
Using this approach offers a remarkable advantage with respect to the generation of the arrays by using eval: you can access to the field od the struct (that is to their content) even not knowing their names.
In the following you can find a modified version of your script in which this approach has been implemented.
The script generate two structs:
the first one, cl_struct_same_length is used to store the rows of the cl_matrix
thesecond one, cl_struct_different_length is used to store arrays of different length
In the script there are examples on how to access to the fileds (that is the arrays) to perform some calculations (in the example, to evaluate the mean of each of then).
You can access to the struct fields by using the functions:
getfield to get the values stored in it
fieldnames to get the names (dynamically generated) of the field
Updated script
Angle = [1 7 15];
for i = 1:length(Angle)
% do some calculations here %%
% % % cl_matrix(i,:) = A.data(:,7);
% Populate cl_matrix
cl_matrix(i,:) = randi(10,1,10)*Angle(i);
% Create a struct with dinamic filed names
cl_struct_same_length.(['cl_' num2str(Angle(i))])=cl_matrix(i,:)
cl_struct_different_length.(['cl_' num2str(Angle(i))])=randi(10,1,Angle(i))
end
% Use "fieldnames" to get the names of the dinamically generated struct's field
cl_fields=fieldnames(cl_struct_same_length)
% Loop through the struct's fileds to perform some calculation on the
% stored values
for i=1:length(cl_fields)
cl_means(i)=mean(cl_struct_same_length.(cl_fields{i}))
end
% Assign the value stored in a struct's field to a variable
row_2_of_cl_matrix=getfield(cl_struct_different_length,(['cl_' num2str(Angle(2))]))
Hope this helps.

Deleting a specific set of elements from a complex nested structure in matlab efficiently

I have a complex nested structure in MATLAB:
a.b.c, a.b.d, a.b.e...a.b.p
a has 4 elements, b has 90 and c has a variable number of elements
I want to delete for example: the 5 element of c,d,e,f,....p for a particular b(i)
How can I do that in one command or most efficiently without having to write down
a(1).b(i).c(5)=[];....
a(1).b(i).p(5)=[];
I believe this is not possible without looping through the elements of the substructure unless you want to apply the change to all elements of a given level
For a selection of elements
Solution for looping through a subset of elements, using dynamic field names
ai=1; % first level index
bi=2; % second level index
rem=[1,5] % elements to remove
for ci='c':'p' % field names to change
a(ai).b(bi).(ci)(rem)=[];
end
For all elements
Example to remove 1st and 5th column from all a(1).b(2)
ia=1; % a index
ib=2; % b index
rem=[1,5]; % columns to remove
a(ia).b(ib)=structfun(#(a)a(setdiff(1:end,rem)),a(ia).b(ib),'unifo',0)
note: is doesn't remove the elements but overwrites the modified parts of the structure omitting the elements to be removed
what the line does
a(ia).b(ib)=structfun(#(a)a(setdiff(1:end,rem)),a(ia).b(ib),'unifo',0)
setdiff(1:end,rem) % elements not in rem
#(a)a( ) % get these elements of
structfun( ,a(ia).b(ib) % this sub array
a(ia).b(ib)= % and overwrite it
finally ,'unifo',0) tells matlab the out put of #(a)a(setdiff(1:end,rem)) is not a single value i.e. still a vector

Extract parts of a big matrix and allocate them in new variables with loop function

I am a total beginner in MATLAB and I hope to find some help here. I have some model prediction results for 80 individuals alltogether in one large matrix. I need to extract the data for each individual from the big matrix, assign them in a new variable/matrix, do some extra calculations and then plot certain information as needed.
To do so, I am trying to write a script with a loop function but in a complicated, or maybe more accurately: in a primitive way!
Simplified Example:
My matrix is called: All_Indi_Data .... its dimension is: 600 rows x 21 columns
%Column 1: grouping variable (e.g., code or ID with values 1,2,3,4,5, etc.);
%Column 2: independent var.;
%Column 3: t;
%Column 4: OBS;
%Column 5: PRED;
i= length (All_Indi_Data);
%% First Indi.
q=1; % indicating the ID of the indi for which I want to extract the data
j=1; % variable added to insure writing start from the first row
for r=1:i
if All_Indi_Data (r,1)==q
Indi_1 (j,1:21) = All_Indi_Data (r,1:21)
j=j+1
end
end
%% Second Indi.
q=q+1
j=1
for r=1:i
if All_Indi_Data (r,1)==q
Indi_2 (j,1:21) = All_Indi_Data (r,1:21)
j=j+1
end
end
.
.
.
1) My first question is: can I allocate these data in new variables (Indi_1, Indi_2, ect.) in a more simple way with or without the loop function?!!! I would appreciate your help a lot.
2) Is there any code or any way to plot these selected parts (according to the grouping variable, e.g. data for Indi_1) from the previously mentioned big matrix without wasting a lot of time and space (wto recopying the core part of the code again and again) for the script, and using the loop function?! in other words, I would like to detect - with loop function & the grouping variable- which values are of interest and then to plot them (e.g. data in colum 3 with data from column 4 for each individual, starting from the first to the last)?!
I hope that I described my problem clearly and hope to hear something from the expert guys :) ...
Thanks a lot in advance ..
Try the following code:
for idx=1:80
pos=find(All_Indi_Data(:,1)==idx);
eval(['Indi_' num2str(idx) '=All_Indi_Data(pos,:);']);
end
What I do is: in each iteration, I search for a value of the ID, indicated in the variable idx. Note that I do not use ´i´ as the name of a variable, because Matlab uses it and ´j´ and the imaginary unit for complex numbers and that could cause problems.
Then, using find I search for the position (or positions) of All_Indi_Data in which I can find the information of that individual. Now I have in the variable ´pos´ the indexes of the rows in which there is information for the individual of interest.
Finally, using eval I extract the data for each individual into a variable. Note that eval combined with a loop makes it easy to create lots of variables. I indicate the rows I want to extract with ´pos´ and, as I want all the columns, I use just ´:´ (you could use ´1:21´ too).
With another similar loop you can plot the information you want. For example:
for idx=1:80
eval(['x=Indi_' num2str(idx) ';']);
% Now I have in X the information for this individual
%Plot the columns of x I want
plot(x(:, 3), x(:,4));
pause; %stay here until a press a key
end

Matlab boxplot for multiple fields

I have this matlab file which has a field called "data". In "data" I have lots of fields for different bonds (x5Q12... etc).
I am trying to produce ONE box plot that contains ONE column from each of the fields (i.e. a box diagram with 36 boxes in it). I tried this code (e.g. to plot a box for column 2 in all of the bonds) but it does't work for me:
boxplot(gilts_withoutdates.data.:(:,2));figure(gcf);
I know my understanding of calling different levels in a structure is a problem here. Any suggestions, please? Many thanks.
You can use STRUCTFUN to extract the data from a particular column of all fields of a structure.
col2plot = 2; %# this is the column you want to plot
%# return, for each field in the structure, the specified
%# column in a cell array
data2plot = structfun(#(x){x(:,col2plot)},gilts_withoutdates.data);
%# convert the cell array into a vector plus group indices
groupIdx = arrayfun(#(x)x*ones(size(data2plot{x})),1:length(data2plot),'uni',0);
groupIdx = cat(1,groupIdx{:});
data2plot = cat(1,data2plot{:});
%# create a compact boxplot
boxplot(data2plot,groupIdx,'plotStyle','compact','labels',labels)
If you're interested in the distribution of the data, I can recommend my function distributionPlot.
B=gilts_withoutdates.data;
b=fieldnames(B);
for a=1:numel(b)
boxplot(B.(b{a})); fig;
end
To plot a boxplot for each of the 5 columns of data for each field you could do this:
pos=1;
for i = 1:numel(b)
for ii=1:5
subplot(numel(b),5,pos);boxplot(B.(b{i})(:,ii));pos=pos+1;
end
end