Matlab: Plotting bar groups - matlab

I want to plot bar plot in which bars are grouped like this:
I have tried this code but I am not getting this type of plot. Please guide me how can I generate plot like above:
load Newy.txt;
load good.txt;
one = Newy(:,1);
orig = good(:,1);
hold on
bar(one,'m');
bar(orig,'g');
hold off
set(gca,'XTickLabel',{'0-19','20-39','40-79','80-159','160-319','320-639','640-1279','1280-1500'})
In each text file there is a list of numbers. The list comprises of 8 values.

You can use histc to count the values within certain edges.
To group bars you can collect them in a single matrix (with the values in each column).
edges = [0 20 40 80 160 320 640 1280 1501];
edLeg = cell(numel(edges)-1,1);
for i=1:length(edLeg)
edLeg{i} = sprintf('%d-%d',edges(i),edges(i+1)-1);
end
n = histc([one,orig],edges);
bar(n(1:end-1,:));
set(gca,'XTickLabels',edLeg)
legend('One','Orig')
I used these as test data
one = ceil(1500.*rand(200,1));
orig = ceil(1500.*rand(200,1));

I got the way to achieve group bars:
I had to plot the data such that there are 8 groups of bars where each group consists of 3 bars.
For that I wrote the data in my each file like this:
Y = [30.9858 1.36816 38.6943
0.655176 6.44236 13.1563
1.42942 3.0947 0.621403
22.6364 2.80378 17.1299
0.621871 5.37145 1.87824
0.876739 5.97647 3.80334
40.6585 68.6757 23.0408
2.13606 6.26739 1.67559
];
bar(Y)

Related

Change colors of stacked bar plot

I want to change the colors of my stacked bar plot but I keep getting an error message
As I need specific colors in my stacked bar plot to match with another graph I set up the color vector: colori with RGB values which I then convert into values between 0 and 1 after creating the figuer I want to change colors of the 15 stacked bars like this:
for i = 1:15
barSNE(i,:).FaceColor = colori(i);
end
here a bit mor of the code:
...
colori = [139,0,0
255,160,122;
255,69,0;
255,165,0;
255,215,0;
154,205,50;
34,139,34;
50,205,50;
255,182,193;
106,90,205;
139,0,139;
32,178,170;
199,21,133;
30,144,255;
0,0,205];
colori = colori ./ 255;
ctMeansT = ctMeans.';
figure(2)
barSNE = bar(ctMeansT, 'stacked');
for i = 1:15
barSNE(i,:).FaceColor = colori(i);
end
However, I get following Error message:
Structure assignment to non-structure object.
Error in viSNE_stacked_bar_plot (line 41)
barSNE(i,:).FaceColor = colori(i);
Colors in the figuere are not changed as expected
Your did a wrong indexing of your arrays barSNE and colori. If I run the code as you posted it above and check the size of both arrays I get
>> size(barSNE)
ans =
1 15
>> size(colori)
ans =
15 3
So barSNE is a one-dimensional array, while colori is a matrix of size 15 x 3. However, you tread it in your code vice versa given your index notation. E.g. If you do colori(i) you do not get the first RGB triplet as desired, but the first single value of the array colori (in your case 139/256 = 0.5451).
Change the indexing within the loop as follows
for i = 1:15
barSNE(i).FaceColor = colori(i,:);
end
and it works. As an example with random numbers for ctMeans (since you haven't provided your original data) I get a bar chart like this

Creating a scatter plot in matlab with different colors and markers for two different grouping variables

I seem to be having problems creating a 2D scatter plot in matlab with two grouping variables which displays different colors for one of them and different markers for the other. The variable "score" has the X and Y values and the two grouping variables are "att21" and "att22".
I use the following code:
f=figure;
gscatter(score(:,1), score(:,2), {att21, att22}, 'br', 'xo');
what I'm getting is:
scatter plot
However, what I want to get is blue for L4 and red for L1 and x for Flake and o for Chunk. I would also like the legend to indicate this.
What am I missing?
Thanks for any help...
OK, I think I figured it out. The solution provided by Noel is good only if I know the number of groups in each grouping variable, but unfortunately this is not the case.
So I came up with the solution if using nested loops.
f=figure;
hold on;
marker = '+o*.xsd';
clr = 'rgbymck';
att1v = unique(att1);
att2v = unique(att2);
attv = [att1v; att2v];
att1count = 1;
att2count = 1;
for k=1:length(score)
att1count = 1;
att2count = 1;
while att1count <= length(att1v)
if isequal(att1(k),att1v(att1count))
while att2count <= length(att2v)
if isequal(att2(k),att2v(att2count))
f=scatter(score(k,1),score(k,2),15,clr(att1count),marker(att2count));
end
att2count = att2count + 1;
end
end
att1count = att1count + 1;
end
end
legend(attv);
Now the scatter plot is OK and its supports up to 7 groups in each variable. The only problem I'm left with is that I can't manage to create a Legend which shows the different labels for all the groups.
All I manage to get is this:plot with bad legend
If anyone has a solution for me it will be great...
Thanks alot
When you are grouping by 2 grouping variables, each with 2 categories, you are implicitly creating 4 different groups, so you have to define the color and markers for the 4 groups, in your case
gscatter(score(:,1), score(:,2), {att21, att22}, 'rrbb', 'xoxo');
But since gscatter will repeat the pattern if the defined color or marker is smaller than the number of groups, you can save 2 characters by doing
gscatter(score(:,1), score(:,2), {att21, att22}, 'rrbb', 'xo');
If you don't know the number of groups in each category, you can obtain them with the command unique and count them, and then use that number to create the markers and colors. For your example
marker = '+o*.xsd';
clr = 'rgbymck';
n_groups_att1 = length(unique(att21));
n_groups_att2 = length(unique(att22));
m = marker(1:n_groups_att2);
c = repmat(clr(1:n_groups_att1),n_groups_att2,1);
c = c(:)';
gscatter(score(:,1), score(:,2), {att21, att22}, c, m);
Just make sure that marker and clr has more elements than possible number of groups in each grouping variable

Sorting 3D array along 3rd dimension

I have a 144x91x92 matrix stored in o3{1}. I'd like to look across the third dimension (representing the days in one season) and sort it. Then, I want to pull out the top 10 and bottom 10 percentile of values including the index of those values. This would find the top 10 and bottom 10 percentile of days for each grid cell (this would be different for each grid cell).
I'm trying the following:
[Y,I] = sort(o3{1},3); % sort o3 along 3rd dimension
o3_sorted = o3{1}(I);
ind_top10 = o3_sorted(90);
ind_bot10 = o3_sorted(10);
But I know I'm not pulling out the top 10 and bottom 10th percentile correct. Plus, this way does not tell me the indices (different for each of the 144x91 grid cells) for the top and bottom 10 percentile of days. I am hoping to end up with 144x91x10 matrices for the top 10 percentile of days, the bottom 10 percentile of days, and the indices for each.
Try it like this:
[~, I] = sort(o3{1},3); %// sort o3 along 3rd dimension
ind_top10 = I(:,:,end-8:end);
ind_bot10 = I(:,:,1:9);
I3 = cat(3, ind_top10, ind_bot10); %// you might want to skip this but and just work with the top and bottom separately from here on
[I1, I2, ~] = ndgrid(1:size(o3{1},1), 1:size(o3{1},2), 1:size(I3,3));
ind = sub2ind(size(o3{1}),I1,I2,I3)
And now
o3{2}(ind)
o3{3}(ind)
%// etc...
Here's a slightly different idea from what Dan had suggested:
%% // Init
clear variables; clc;
%% // Generate some data:
o3 = cell(3,1);
for indO = 1:3
o3{indO} = randi(intmax('uint16'),144,91,92,'uint16');
end
%% // Find 10 & 90 percentiles:
percentiles = cat(3,prctile(o3{1},10,3),prctile(o3{1},90,3));
%% // Find indices of relevant values
select_bot10 = bsxfun(#ge,o3{1},percentiles(:,:,1)); %// replace #ge with #gt if needed
select_top10 = bsxfun(#le,o3{1},percentiles(:,:,2)); %// replace #le with #lt if needed
%// Another optional way to index the values if required:
[rb,cb,vb] = ind2sub(size(select_bot10),find(select_bot10));
[rt,ct,vt] = ind2sub(size(select_top10),find(select_top10));
%% // Get values from o3{1..3} etc.
bot10 = o3{1}(select_bot10);
top10 = o3{1}(select_top10);
%// etc.
This solution might not be suitable for your specific needs as it is, but adaptations should be straightforward. Also note that since exact percentiles are taken, the number of elements would probably differ between bot10 and top10.
Credit for the 3D find goes to Kenneth Eaton / gnovice.

about labeling the x axis

I have many data need to be plotted as waterfall in matlab. I have more than 10 columns of data, each column represents one data data set. I put all data in a big matrix such that the first data set put in the first row of matrix, the second data set will be in the second row ... etc. After all those data stored in a matrix, I use the waterfall to plot those data. For each column, it contains about 10,000 data points which corresponds to x variable ranged from -5 to 5. But in the waterfall, it shows 0 to 10, 000 instead of -5 to 5 in the x axis. How do I force matlab to show the correct range? thx
mydata = zeros(13, 10000);
mydata(1, :) = ... ; % first data set
mydata(2, :) = ... ; % second data set
...
mydata(13, :) = ... ; % last data set
waterfall(mydata)
If you look at the documentation for waterfall (you can do this easily by placing the cursor in the command in your editor and hitting F1), you will see that you can invoke the waterfall command with different syntax . .
% Syntax
waterfall(Z)
waterfall(X,Y,Z)
waterfall(...,C)
waterfall(axes_handles,...)
h = waterfall(...)
Rather than just call the waterfall plot with the data Z, supply it with the X and Y range data also. For example . . .
mydata = rand(13, 10000);
Y = 1:size(mydata,1);
X = linspace(-5, 5,size(mydata,2));
waterfall(X, Y , mydata)

Plotting multiple lines within a FOR loopin MATLAB

Okay so this sounds easy but no matter how many times I have tried I still cannot get it to plot correctly. I need only 3 lines on the same graph however still have an issue with it.
iO = 2.0e-6;
k = 1.38e-23;
q = 1.602e-19;
for temp_f = [75 100 125]
T = ((5/9)*temp_f-32)+273.15;
vd = -1.0:0.01:0.6;
Id = iO*(exp((q*vd)/(k*T))-1);
plot(vd,Id,'r',vd,Id,'y',vd,Id,'g');
legend('amps at 75 F', 'amps at 100 F','amps at 125 F');
end;
ylabel('Amps');
xlabel('Volts');
title('Current through diode');
Now I know the plot function that is currently in their isn't working and that some kind of variable needs setup like (vd,Id1,'r',vd,Id2,'y',vd,Id3,'g'); however I really can't grasp the concept of changing it and am seeking help.
You can use the "hold on" function to make it so each plot command plots on the same window as the last.
It would be better to skip the for loop and just do this all in one step though.
iO = 2.0e-6;
k = 1.38e-23;
q = 1.602e-19;
temp_f = [75 100 125];
T = ((5/9)*temp_f-32)+273.15;
vd = -1.0:0.01:0.6;
% Convert this 1xlength(vd) vector to a 3xlength(vd) vector by copying it down two rows.
vd = repmat(vd,3,1);
% Convert this 1x3 array to a 3x1 array.
T=T';
% and then copy it accross to length(vd) so each row is all the same value from the original T
T=repmat(T,1,length(vd));
%Now we can calculate Id all at once.
Id = iO*(exp((q*vd)./(k*T))-1);
%Then plot each row of the Id matrix as a seperate line. Id(1,:) means 1st row, all columns.
plot(vd,Id(1,:),'r',vd,Id(2,:),'y',vd,Id(3,:),'g');
ylabel('Amps');
xlabel('Volts');
title('Current through diode');
And that should get what you want.