Populating Matlab legend using for loop - matlab

I am attempting to populate a legend of a bar graph for the corresponding number of quantities being plotted, which is variable. I have included a typical legend's plotting scheme below, though I am attempting to replicate this for a variable number of elements in the vector 'test'. I understand that this is relatively simple procedure, but my experience is limited and any help would be appreciated.
test=[1,2,3,4,5]
bar(diag(test), 'stacked')
legend('label1','label2','label3','label4','label5');
xlabel('labels')
title('Title')

You can combine the labels in one array. That way you would be able to work with a dynamic number of labels.
This does the same thing with your code, but the legend function is called with an array:
test=[1,2,3,4,5]
bar(diag(test), 'stacked')
legend(["label1", "label2", "label3", "label4", "label5"]);
xlabel('labels')
title('Title')
Note that I used strings (") instead of chars (') because char arrays are harder to operate as arrays.
You can also automate the names completely,
test=[1,2,3,4,5]
bar(diag(test), 'stacked')
legendNames = "label" + test;
legend(legendNames);
xlabel('labels')
title('Title')

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.

MATLAB for loop through columns to plot multiple lines

I need your help again :). I'm trying to plot multiple lines for a very large dataset. To start easier, I divided the dataset to get a TABLE in Matlab that contains 6 columns, with the first column representing the date that I want on my x-axis. Now I want to plot the other columns (and in the original file are a lot more than 6 columns) on the y axis, using a for loop. I tried the following, with no success:
hold on
for i=2:1:6
plot(Doldenstock(:,1), Doldenstock(:,i));
end
hold off
As I understand this, this code would do exactly what I want for columns 2,3,4,5,6. However, I always get the same error code:
Error using tabular/plot
Too many input arguments.
Error in Plotting_bogeo (line 6)
plot(Doldenstock(:,1), Doldenstock(:,i));
Now, I don't know if maybe for loops like this don't work for tabes but only for arrays?
Thanks for your help in advance!
Cheers,
Tamara
The function plot(x) expect x to be a scalar, a vector, or a matrix. But in your case the input is a table, because accessing a table with parentheses return a table, which is not supported.
If you read the doc "how to access data in a table" you will figure out that you need to use curly brace {} to extract the raw data (in your case a 1D matrix).
So use:
plot(T{:,1},T{:,2})

Octave - Convert number-strings from CSV import file to numerical matrix

I'm writing a code to import data from a CSV file and convert it into an Octave matrix. The imported data can be seen in the following snap:
In the next step I added the following command to delete the commas and "":
meas_raw_temp = strrep(meas_raw_temp,',',' ')
And then I get the data format in the following form:
The problem is that Octave still sees the data as 1 single 1-dimensional array. i.e., when I use the size command I get a single number, i.e. 2647. What I need to have is a matrix output, with each line of the snaps being a row of the matrix, and with each element separated.
Any thoughts?
Here's what's happening.
You have a 1-dimensional (rows only) cell array. Each element (i.e. cell) in the cell array contains a single string.
Your strings contain commas and literal double-quotes in them. You have managed to get rid of them all by replacing them in-place with an 'empty string'. Good. However that doesn't change the fact that you still have a single string per cell.
You need to create a for loop to process each cell separately. For each cell, split the string into its components (i.e. 'tokens') using ' ' (i.e. space) as the delimiter. You can use either strsplit or strtok appropriately to achieve this. Note that the 'tokens' you get out of this process are still of 'string' type. If you want numbers, you'll need to convert them (e.g. using str2double or something equivalent).
For each cell you process, find a way to fill the corresponding row of a preallocated matrix.
As Adriaan has pointed out in the comments, the exact manner in which you follow the steps above programmatically can vary, therefore I'm not going to provide the range of possible ways that you could do so, and I'm limiting the answer to this question to the steps above, which is how you should think about solving your problem.
If you attempt these steps and get stuck on a 'programmatic' aspect of your implementation, feel free to ask another stackoverflow question.

Create a loop using part of variable name in MATLAB

I am a beginner in Matlab and have not been able to find an answer to my question so far. Your help will definitely be very much appreciated.
I have 70 matrices (100x100), named SUBJ_1, SUBJ_2 etc. I would like to create a loop so that I would calculate some metrics (i.e. max and min values) for each matrix, and save the output in a 70x2 result matrix (where each row would correspond to the consecutively named SUBJ_ matrix).
I am struggling with both stages - how to use the names of individual variables in a 'for' loop and how to properly save individual outputs in a combined array.
Many thanks and all the best!
Don't use such variable names, create a big cell array named SUBJ and put each Matrix in it.
r=zeros(numel(SUBJ),2)
for idx=1:numel(SUBJ)
r(idx,1)=min(min(SUBJ{idx}))
r(idx,2)=max(max(SUBJ{idx}))
end
min and max are called twice because first call creates maximum among rows, second call among columns.
Even though this is in principle possible in Matlab, I would not recommend it: too slow and cumbersome to implement.
You could instead use a 3-D matrix (100x100x70) SUBJ which would contain all the SUBJ_1 etc. in one matrix. This would allow you to calculate min/max etc. with just one line of code. Matlab will take care of the loops internally:
OUTPUT(:,1) = min(min(SUBJ,[],1)[],2);
OUTPUT(:,2) = max(max(SUBJ,[],1)[],2);
Like this, OUTPUT(1,1) contains min(min(SUBJ(:,:,1))) and so on...
As to how to use the names of individual variables in a 'for' loop, here gives an example:
SUBJ = [];
for idx = 1:70
term = eval(['SUBJ_',num2str(idx)]);
SUBJ = [SUBJ; max(max(term)),min(min(term))];
end

Choose and plot lines in a structure

Im having an issue specifying particular lines in a structure and plotting them.
I use tblread to take data from a file:
table_data = tdfread(table,',');
The table has both numerical and text data, looks a bit like this:
protocol,num_nodes,scale_physical,density,trace,reliability
etx,50,4.7045454546,4.94,heavy,72.7
nh,50,3.8275862069,4.96,heavy,64.27
rtt,50,4.5454545455,5.12,heavy,50.44
etx,50,3.8275862069,4.88,light,93.33
nh,50,4.7272727273,4.94,light,82.45
The resultant data type is a scalar structure called table_data. I can plot each column against each other using:
scatter(table_data.scale, table_data.reliability)
What I would like to achieve is to plot specific elements in the columns defined by a value in another column. Eg. plot the scale vs reliability where protocol = "nh".
Essentially I would like to achieve this end result like:
scatter(table_data.scale(table_data.protocol='nh'), table_data.reliability(table_data.protocol='nh'),'r')
hold on
scatter(table_data.scale(table_data.protocol='rtt'),table_data.reliability(table_data.protocol='rtt'),'b')
To differentiate the two types of points on the plot.
Is there any way of achieving this in a manor alluded to above.
Thanks.
EDIT:
solution is as follows:
scatter(table_data.scale(table_data.protocol=='n'),table_data.reliability(table_data.protocol=='n'), 'r')
hold on
scatter(table_data.scale(table_data.protocol=='e'),table_data.reliability(table_data.protocol=='e'), 'b')
In the structure The text is held as array or characters rather than a cell. table_data.protocol then points only references the first character in the array.
I think you want to replace the single equals in:
scatter(table_data.scale(table_data.protocol='nh'), table_data.reliability(table_data.protocol='nh'),'r')
to be a double equals like:
scatter(table_data.scale(table_data.protocol=='nh'), table_data.reliability(table_data.protocol=='nh'),'r')
i.e. you want a comparison operation instead of an assignment operation.