How to put random labels in stacked bar plot matlab - matlab

I create a horizontally stacked bar plot as below:-
data(1,:)=[0,55,87,96,97,98,99,100,102,125,130];
data(2,:)=[0,55,65,107,110,129,131,0,0,0,0];
data(3,:)=[0,60,104,108,128,130,0,0,0,0,0];
barh(data,'stacked')
axis ij
set(gca, 'xlim',[0,1000], 'box','off');
The output is this:
My question is that i want to put labels inside each box randomly like say this:-
Labels can be any digit or any letter, not neccesarily 1.

Here is one option:
y = repelem(1:size(data,1),size(data,2)-1);
x = (cumsum(data(:,2:end),2)-data(:,2:end)./2).';
labels = data(:,2:end).'>0;
text(x(labels),y(labels),num2str((1:nnz(labels)).'))
This will print a number increasing by 1 in each box:
If you want to put random numbers, replace (1:nnz(labels)).' with rand(nnz(labels),1). If you want to put characters or mixed content use a cell array with one cell for a label.

Related

Creating a legend in MATLAB that includes scatter plots and normal plots

I want my legend to include the line from the plot and the marker from the scatterplot. For example,
rest = importdata('test.xlsx');
x = test.data(:,1);
y = test.data(:,2);
xx = min(x):0.001:max(x);
yy = interp1(x,y,xx,'cubic');
figure
s1 = scatter(x,y, 'filled', 'k');
hold on
p1 = plot(xx,yy, '--k');
legend(p1, 'x1');
This code creates the legend with only the dashes from the plot and not points from the scatterplot. I would like the legend to have the both the point and the dashed line at the same label. Something like "-.-"
Any help is much appreciated.
Thanks.
Option 1
Make a dummy plot with no data (nan) for the legend (also, as you can see here you can plot all the elements with one call to plot:
p = plot(nan,nan,'--ok', xx,yy,'--k', x,y,'ok');
set(p,{'MarkerFaceColor'},{'k'}); % fill the circles
legend('x1');
The result:
Option 2
Insted of legend(p1, 'x1');, write this:
[~,ico] = legend(p1,'x1'); % create the legend, and get handels to it's parts
ico(3).Marker = 'o'; % set the marker to circle
ico(3).MarkerFaceColor = 'k'; % set it's fill color to black
ico is:
3×1 graphics array:
Text (x1)
Line (x1)
Line (x1)
The first element is the text 'x1' in the figure. The second element is the dashed line, and the third is the (not-exist) marker of p1. This third element is reserved for cases like plot(xx,yy,'--ok'); where the legend include both marker and a line, but the line (in the legend) is represented with two points and the marker with only one, so we need different objects for them. Try to see what happens if you type ico(2).Marker = 'o'; in the example above.
Legend in MATLAB is additional axes that contains the same primitive object like lines and text.
If you want to draw custom legend the simple way will be using primitive commands line, text and patch for rectangles with filling. Also you can add one more axes object as a container.
By specifying p1 in the legend command you are telling MATLAB to only insert an item in the legend for the line corresponding to handle p1 - which is what you are seeing.
In your example case you just want
>>legend({'label_for_scatter','label_for_plot'});

Legend in multiple plots Matlab

How can I put the legend on each graph separately like (figure 2) instead of putting the legend on the side like (figure 1) ?
Figure 1
Figure 2
Probably the easiest thing would be to use the text(x,y,textstring) function to put some text at the final data points of each of your curves (e.g. x, y point of largest x, for each curve). The arguments x, y can be vectors, and the argument textstring can be a cell array of strings.
Create an array of final data points separately for x and y.
xcoords = [x0_final x1_final ...xn_final];
ycoords = [y0_final y1_final ...ym_final];
Create a cell array containing your legend strings of the same length as those xcoord and ycoord arrays
legend_strings = {'T0 = 0.5', 'T0 = 0.7' ...};
Then a call to text(xcoords,ycoords,legend_strings) after your plot should do the labeling you want.
The best way to comment on each line would be to add labels or text instead of legend.
For instance:
1)
labeledge(h,s,t,'T_0=1.5s')
2)
txt = texlabel('T_0=1.5s')
text=text(1,1.00E-04,txt)

Stacked bar from Table in matlab

I want to create a stacked bar chart from a table. Here there is a MWE of the type of table I am looking at:
clear all;
country1=rand(5,1);
country2=rand(5,1);
country3=rand(5,1);
country4=rand(5,1);
country5=rand(5,1);
date=1990:1994;
T=table(date',country1,country2,country3,country4,country5);
T.Properties.VariableNames{1}='date';
T.Total=sum(T{:,2:end},2);
T{:,2:end} = T{:,2:end}./T.Total;
A = table2array(T);
A(:,[1,end])=[];
A=sort(A,2);
TT=array2table(A,'VariableNames',{'country1','country2','country3','country4','country5'});
TT.Date=T.date;
TT.Total=T.Total;
T_new=table(TT.Date, TT.country1,TT.country2,TT.country3,TT.country4,TT.country5,TT.Total);
T_new.Properties.VariableNames=T.Properties.VariableNames;
T_new.World=sum(T{:,2:4},2);
T_new.World=1-(T_new.country4+T_new.country5);
T_new(:,[2:4,end-1])=[];
T_new
date country4 country5 World
____ ________ ________ _______
1990 0.2933 0.29471 0.41199
1991 0.31453 0.34511 0.34035
1992 0.22595 0.29099 0.48307
1993 0.26357 0.33336 0.40306
1994 0.28401 0.28922 0.42677
Type of Stacked BAR
====================
Based on the T_new table I want to create a stacked bar graph. In the 'x' axis the chart should show the dates (1990,1991 etc) and for each date should be one stacked bar. So, for example, for 1990 there is should be one bar stacking the values 0.2933 0.29471 0.41199
Ideally, in the stack bar I want also to include the labels of (country1, country2, world) for the correspending values.
How I can do that in matlab ?
You can do the following:
bar(T_new{:,1},T_new{:,2:end},'stacked')
legend(T_new.Properties.VariableNames(2:end))
The code you've provided contains an erron at line:
T{:,2:end} = T{:,2:end}./T.Total
Error using ./
Matrix dimensions must agree.
Error in stacked_bars (line 14)
T{:,2:end} = T{:,2:end}./T.Total;
since T{:,2:end} is a (5 x 6) matrix and T.Total is a (5 x 1) array
You can fix it replacing that line with, for example:
T{:,2:end}=bsxfun(#rdivide,T{:,2:end},T.Total)
Once fixed the error, an alternative way (with respect to the already posted answer) to plot the labels could be to use the text function to draw a string in each of the stackedbars.
You can identify the x and y coordinate of the point in which to draw the string this way:
x: for each set of bars, is the corresponding date (you need to shift that value a little on the left in order to centre the text with respect to the bar since text uses the x coordinate as starting point
y: for the first label (the lower) could be simply the half of the height of the bar; from the second bar on, you need to add the height of the previous ones
A possible implementation of this approach could be the following:
% Get the T_new data
x=table2array(T_new)
x=x(:,2:end)
% Ientify the number of bars
n_s_bars=size(x,2)
% Open a Figure for the plot
figure(123)
% Plot the stacked bars
bar(T_new{:,1},T_new{:,2:end},'stacked')
% Get the names of the table variables
v_names=T_new.Properties.VariableNames
% Loop over the dates
for i=1:length(date)
% Create the label string:
% country_x (or world)
% percentage
str=sprintf('%s\n%f',v_names{2},x(i,1))
% Print the label in the center of the first bar
tx=text(date(i)-.3,x(i,1)/2,str,'Color',[1 1 1])
% Loop over the bars, starting from the second bar
for j=2:n_s_bars
% Create the label string:
% country_x (or world)
% percentage
str=sprintf('%s\n%f',v_names{j+1},x(i,j))
% Print the label in the center of the first bar
tx=text(date(i)-.3,sum(x(i,1:j-1))+x(i,j)/2,str)
end
end
Over the loops, the following image is generated:
Hope this helps,
Qapla'

How to get length of YTickLabels in MATLAB?

I have a MATLAB subplot figure. I need the YLabels to left align justify. To do this I am setting the Position property for each ylabel. My problem is the subplots are being created programmatically and therefore I don't know what to set the position as.
In MATLAB I want to use the longest/widest YTickLabel as a reference point for positioning. To do that I want to get the length of each label. I am able to get the YTickLabels by doing:
% Set Label format as string
set(gca, 'YTickLabel', num2str(transpose(get(gca, 'YTick'))))
% Get axis YTickLabels
ax = gca;
labels = get(ax, 'YTickLabel');
% Print labels to console
disp(labels)
I would like to iterate through the labels and find the length of the longest label. I've tried accessing them as a cell array but get 'Cell contents reference from a non-cell array object error.' And when I try matrix indexing nothing prints.
Does anyone know if it is possible to get the length of each individual YTickLabel value?
Useful info:
MATLAB R2014b
By "length of each individual YTickLabel value" I understand that you wish to get the number of characters forming each label.
It's quite easy using the numel function, which outputs the number of elements in a cell for an example. Since labels are stored in a cell array, we can use the fancy function cellfun to apply numel to each cell, then convert to a numeric array with cell2mat
In short you can use this:
LabelLength = cell2mat(cellfun(#(x) numel(x),labels,'uni',0))
here is some sample code to illustrate:
clear
clc
close all
x = 1:5;
y = rand(size(x));
scatter(x,y,40,'r','filled')
set(gca,'YTick',[1 3 5],'YTickLabel',{'One';'ThisIsThree';'AndFive'})
grid on
labels = get(gca,'YTickLabel')
LabelLength = cell2mat(cellfun(#(x) numel(x),labels,'uni',0))
and output:
LabelLength =
3
11
7
You could replace cellfun with this equivalent for-loop:
LabelLength = zeros(numel(labels),1);
for k = 1:numel(labels)
LabelLength(k) = numel(labels{k});
end
LabelLength
Note that as a workaround offering quite a lot of flexibility, you could replace the YTickLabels by text objects, for which you can set the HorizontalAlignment property to left for the text to be left-justified.
Hope that helps!

Changing how many tick labels on a plot in MATLAB

I have 3 arrays,
y = [1,4,6,8,2,5,......];
x = [1,2,3,4,5,6,......];
xlabel = {'label1','label2','label3',........};
where each element in xlabel is the label for each element of the x array.
I am plotting this using:
plot(x,y);
set(gca,'xtick',x,'xticklabel',xlabel);
But because my arrays hold thousands of elements I am getting a black bar as a label because MATLAB is printing every label (see image).
How do I change this so MATLAB only prints a select few of my xlabels?
You can do for example:
selected = 1:100:numel(x); % change the "100" as desired
set(gca,'xtick',x(selected),'xticklabel',xlabel(selected));