Make squared in legend instead of lines Matlab - matlab

I have the following code, which plots a 'map' using imagesc, and provides a legend, see output attached.
I am trying to replace the lines in the legend with solid squares. My attamps to far leave the lines and ad hollow squares (including a random square in the top left corner of the figure)
figure(6)
imagesc(lut)
title('Ditribution of Land use Types')
ylabel('Longitude')
xlabel('Latitude')
caxis([0, 7])
myColorMap = jet(6);
imagesc(lut, 'AlphaData', ~isnan(lut))
colormap(myColorMap);
L = line(ones(6), ones(6));
set(L, {'Color'}, num2cell(myColorMap, 2))
legend(L, {'Forest','Shrubland','Savanna','Grassland','Agricultural','Barron'})
set(L(:),'Marker','s')
grid on
ax = gca
ax.GridAlpha = .2
ax.XTick = [5 10 15 20 25 30 35 40];
ax.YTick = [5 10 15 20 25 30];
ax.XTickLabel = {'118^{o}E','123^{o}E','128^{o}E', '133^{o}E', '138^{o}E', '143^{o}E','148^{o}E', '153^{o}E'};
ax.YTickLabel = {'13^{o}S','18^{o}S','23^{o}S','28^{o}S','33^{o}S','38^{o}S'};
ax.TickLength =[0.0 0.0]

Use nan to create invisible data (thanks #matlatbgui), and set L with all needed properties for no line and filled square markers:
% some arbitrary data:
N = 30;
lut = diag(1:N)*ones(N)+(diag(1:N)*ones(N)).';
% coloring settings:
caxis([0, 7])
myColorMap = jet(6);
% plotting:
imagesc(lut, 'AlphaData', ~isnan(lut))
colormap(myColorMap);
% Setting the legend:
L = line(nan(6), nan(6),'LineStyle','none'); % 'nan' creates 'invisible' data
set(L, {'MarkerEdgeColor'}, num2cell(myColorMap, 2),...
{'MarkerFaceColor'},num2cell(myColorMap, 2),... % setting the markers to filled squares
'Marker','s');
legend(L, {'Forest','Shrubland','Savanna','Grassland','Agricultural','Barron'})
and you don't need your line:
set(L(:),'Marker','s')

The square on the upper-left corner is obviously due to set(L(:),'Marker','s') which draws a square at the start and end points of the lines, at [1, 1]. Instead of changing the 'Marker', if you increase the 'LineWidth', you get much better results with:
L = line(ones(6), ones(6));
legend(L, {'Forest','Shrubland','Savanna','Grassland','Agricultural','Barron'})
set(L(:), 'LineWidth', 10)
With this output:
So if you are not restricted to make squares, I believe wide rectangles are better flags for color.

Related

Adding a legend when using imagesc, including white for NaN

I have a 35x43 matrix of data with vales ranging from 1-6 and lots of NaNs.
I want to NaNs to be white, and the numbers to each be a different colour. I need a legend with the 6 different colour and labels on it.
I can achieve most of this with the following code, however the colours in the legend do not match the colours in the figure. See code below
figure(6)
subplot(1,2,1)
imagesc(lut)
title('Highest Weighted Predictor variable for each Pixel')
ylabel('Longitude')
xlabel('Latitude')
caxis([0, 7])
myColorMap = jet(7);
myColorMap(1,:) = 1;
colormap(myColorMap);
M = jet(7); % Notice the 3, here and below
hold on
L = line(ones(7),ones(7));
set(L,{'color'},mat2cell(M,ones(1,7),3))
[legh,objh,outh,outm] = legend('First','Second','Location','Southeast');
set(objh,'linewidth',200);
legend('Forest','Shrubland','Savanna','Grassland','Agricultural','Barron');
grid on
ax = gca
ax.GridAlpha = .2
ax.XTick = [5 10 15 20 25 30 35 40];
ax.YTick = [5 10 15 20 25 30];
ax.XTickLabel = {'118^{o}E','123^{o}E','128^{o}E', '133^{o}E', '138^{o}E', '143^{o}E','148^{o}E', '153^{o}E'};
ax.YTickLabel = {'13^{o}S','18^{o}S','23^{o}S','28^{o}S','33^{o}S','38^{o}S'};
ax.TickLength =[0.0 0.0]
To display the NaN values as white I would use something like this. Then for your colormap, just use jet(6). Then the colors will match up just fine.
lut = [1:6 NaN];
myColorMap = jet(6);
imagesc(lut, 'AlphaData', ~isnan(lut))
colormap(myColorMap);
L = line(ones(6), ones(6));
set(L, {'Color'}, num2cell(myColorMap, 2))
legend(L, {'Forest','Shrubland','Savanna','Grassland','Agricultural','Barron'})
I would suggest an alternative solution using a colorbar with individual ticks:
%// example data
lut = randi(6,35,43);
lut(1:23:end) = NaN;
%// parts of your your code
figure(6)
% subplot(1,2,1)
imagesc(lut)
title('Highest Weighted Predictor variable for each Pixel')
ylabel('Longitude')
xlabel('Latitude')
caxis([0, 7])
myColorMap = jet(7);
myColorMap(1,:) = 1;
colormap(myColorMap);
M = jet(7); % Notice the 3, here and below
hold on
%// colorbar
c = colorbar
c.Ticks = (1:6)+0.5
c.TickLabels = {'Forest','Shrubland','Savanna','Grassland','Agricultural','Barron'}

How to fix the legend of this boxplot in matlab?

The legend of this boxplot comes with the same color! How can I fix this? How can I move the x-axis lable a little bit lower ?Thanks for your help.
close all
clc;clear;
f=figure;
Temp_O=[-0.234115422389688;-0.153751688636750;3.03158128172032;-0.746185319551222;0.491616009046725;1.17490826218458;0.495331079652895;0.757394580248284;1.28467417069223;0.710444835069366;-0.979521722186138;-0.216850422633648;0.0596632891728577;-0.525362330358090;0.681608181821661;-0.995216710339821;-0.706416688978551;-0.147700048468633;-0.145946504735073;0.355209739265580;1.25860455564176;0.970569089382961;3.99404165520844;0.433235373567272;1.37023527554759;1.45032207715449;2.00968917969203;0.840884198707613;2.08558564237223;2.05435556980046;-15.5517060656394;3.18991806590028;1.28277879106186;2.15931490153483;3.19647581545030;2.97877640768595;0.0857405478541730;-1.59362648933500;-2.18109410889313;0.751077088333943;0.795072796032814;4.18896005388773;-0.591461781602054;-0.229818549439720];
position_O = 5:5:25;
position_O=position_O';
g = [ones(10,1); 2*ones(10,1); 3*ones(10,1) ;4*ones(10,1);5*ones(4,1)];
box_O = boxplot(Temp_O,g,'colors','b','positions',position_O,'width',0.8);
h=findobj(gca,'tag','Outliers');
delete(h)
set(gca,'XTickLabel',{' '})
hold on
Temp_S=[-0.234069549668875;-0.0803021151079149;0.166729084507040;-0.991371043478263;0.320651878289472;0.118699258741257;-0.190944834558825;0.540367970198674;1.02556298920863;0.112849364285713;-0.395341229166667;0.382362326388889;-1.40591456976744;0.247202120000001;-1.33262568333333;-1.27793610544218;0.0400995141843974;-1.32333150653595;-1.84221947163121;0.407607340136054;0.264276120300749;-0.337747273809525;1.03841878571429;-1.41048786507936;0.901727821428570;-1.03012908482143;2.69786876785714;-0.691010535714286;1.66913088345865;0.684260974489794;-10.3923539047619;1.04994314285714;2.13557031632653;3.87736348701299;7.38705700000000;0.0451628482142860;-3.69094742857143;-1.14071104081633;-3.15830153968254;-4.41399970408163;6.09908001655629;0.0267684861111112;-2.67854298170732;0.925146217948717;];
position_S = 6.8:5:26.8;
position_S=position_S';
box_S = boxplot(Temp_S,g,'colors','r','positions',position_S,'width',0.8);
h=findobj(gca,'tag','Outliers');
delete(h)
legend(findobj(gca,'Tag','Box'),'Group1','Group2')
set(gca,'XTickLabel',{' '}) ;
hold off
text('Position',[5,-11],'String','S')
text('Position',[10,-11],'String','M')
text('Position',[15,-11],'String','L')
text('Position',[20,-11],'String','V')
text('Position',[25,-11],'String','C')
xlabel('Types','FontSize',10);
% set(get(gca, 'XLabel'), 'Position', [0 .2 0]); %
ylim([-10.5 7.8]);
The issue is that you're only displaying the legend for the first two boxes (yours has a total of 10 boxes) and both of these are red. The first 5 boxes that are found are red and the last 5 are blue. Instead you could use the first and last box.
%// Create the box plot
box_S = boxplot(Temp_S, g, 'colors', 'r', 'positions', position_S, 'width', 0.8);
%// Get all of the box plot objects
boxes = findobj(gca, 'Tag', 'Box');
legend(boxes([end 1]), 'Group1', 'Group2')
You could do this more robustly though with the following:
boxes = findobj(gca, 'Tag', 'box');
%// Sort by xposition
[~, ind] = sort(cellfun(#mean, get(boxes, 'XData')));
%// Apply legends to one red and one blue one.
legend(boxes(ind(1:2)), 'Group1', 'Group2');
And to move the xlabel a little lower, you can simply adjust it's Position property.
yrange = diff(get(gca, 'YLim'));
XL = get(gca, 'XLabel');
original = get(XL, 'Position');
%// Add an extra 1% padding
set(XL, 'Position', original - [0 0.01*yrange 0])
Here is a small example (I only kept the necessary stuff):
x1 = randn(44,1);
x2 = randn(44,1);
pos1 = (5:5:25)';
pos2 = (6.8:5:26.8)';
g = repelem([1 2 3 4 5], [10 10 10 10 4]);
h1 = boxplot(x1, g, 'Colors','b', 'Positions',pos1, 'Width',0.8);
hold on
h2 = boxplot(x2, g, 'Colors','r', 'Positions',pos2, 'Width',0.8);
hold off
legend([h1(5,1),h2(5,1)], {'Group1','Group2'})
To quote help boxplot:
% H = BOXPLOT(...) returns the handle H to the lines in the box plot.
% H has one column per box, consisting of the handles for the various
% parts of the box. For the traditional plotstyle, the rows correspond
% to: upper whisker, lower whisker, upper adjacent value, lower adjacent
% value, box, median, and outliers. For the compact plotstyle, the rows
% correspond to: whiskers, box, median outer, median inner, and outliers.
% If median comparison intervals are indicated with markers, H will have
% two more rows for notch lo and notch hi. If medianstyle or boxstyle
% have been set explicitly, the meaning of the rows will adjust
% accordingly.

MATLAB: How do I shade plot area with increasing and decreasing shades of a color

I want to plot an area of a graph (x = 1:24, y = -1:1) with one color (black), which I then want to decrease/increase in shading in terms of the time of day. So, that I have a plot which is 'dark' in the background at night and 'light' during the day with x being hours of day and y being a data value. My sunrise would be at 6.8 and my sunset would be at 22. I would then overlay scatter plots with data on top.
I have tried messing around with patch and area but with no luck. Here is some code I got from elsewhere on the internet but I'm not sure how to proceed:
% Define x, f(x), and M(x)
x = linspace(6.8, 22)';
f = sin(x)+cos(x);
M = x.^2;
% Define the vertices: the points at (x, f(x)) and (x, 0)
N = length(x);
verts = [x(:), f(:), x(:) zeros(N,1)];
% Define the faces to connect each adjacent f(x) and the corresponding points at y = 0.
q = (1:N-1)';
faces = [q, q+1, q+N+1, q+N];
p = patch('Faces', faces, 'Vertices', verts, 'FaceVertexCData', [M(:); M(:)], 'FaceColor', 'interp', 'EdgeColor', 'none')
So I want the end result to be similar to the image attached below (note faint shading - I would like the gradient stronger), but with x = 1:24 and y = -1:1.
Since you ignored my request to include the results of your MATLAB code in your question, I had to look into my crystal ball to determine that your "messing around" resulted in the following error message:
Error using patch
While setting the 'Vertices' property of Patch:
Value must be a 1x2 or 1x3 vector of numeric type
Error in X (line 13)
p = patch('Faces', faces, 'Vertices', verts, 'FaceVertexCData', [M(:); M(:)], 'FaceColor', 'interp', 'EdgeColor', 'none')
This can be resolved by concatenating the vertices vertically instead of horizontally in line 8:
verts = [x(:), f(:); x(:), zeros(N,1)];
This yields the following plot:
This is of course not what you want.
Actual Solution
You can build up your background from 5 rectangles:
x = [0;
6; % 'First daylight'
6.8; % Full brightness
22; % Beginning of 'sunset'
22.8; % Complete darkness
24];
vertices = [repmat(x,2,1), [ones(size(x)); -1.*ones(size(x))]];
faces = [1:5; 2:6; 8:12; 7:11].';
color = repmat([0 0 0; % 'Night' color
0 0 0;
1 1 1; % 'Day' color
1 1 1;
0 0 0;
0 0 0],2,1);
patch('Faces',faces, ...
'Vertices',vertices, ...
'FaceVertexCData',color, ...
'FaceColor','interp', ...
'EdgeColor','red');
xlim([0 24]);
You make the vertices of the 'night' rectangles black and the vertices of the 'day' rectangle white by assigning the appropriate RGB values to the FaceVertexCData property.
The color of 'sunrise'/'sunset' rectangles is then interpolated between black and white by setting the FaceColor property to 'interp'.
The EdgeColor has only been set to 'red' to illustrate how the background is constructed. Set the property to 'interp' to make the lines disappear.

MATLAB Multiple(parallel) box plots in single figure

I'm using the boxplot function in MATLAB. I need to plot boxplots for 6 different datasets for 6 'XTicks' i.e each tick in the x axis should contain 6 corresponding boxes, whiskers, median lines and set of outliers within it's domain. I tried manipulating the 'XTick' property by setting offsets for each variable, but it doesn't apply for boxplot() as it would for a normal plot(). I'm also not able to add legends.
A 3 variable equivalent of my problem would like the following:
Edit:
The following is the code snippet that needs to be modified
TreadmillData = randi([20,200],69,6);
Speeds = {'1.5mph' '2.5mph' '3.5mph' '4.5mph' '5.5mph' '6.5mph'};
DeviceColors = {'r' 'g' 'c' [0.5 0 0.5] 'b' [1 0.5 0]};
Pedometer1 = TreadmillData(1:7:end,:);
Pedometer2 = TreadmillData(2:7:end,:);
Pedometer3 = TreadmillData(3:7:end,:);
Pedometer4 = TreadmillData(4:7:end,:);
Pedometer5 = TreadmillData(5:7:end,:);
Pedometer6 = TreadmillData(6:7:end,:);
GroupedData = {Pedometer1 Pedometer2 Pedometer3 Pedometer4 Pedometer5 Pedometer6};
legendEntries = {'dev1' 'dev2' 'dev3' 'dev4' 'dev5' 'dev6'};
figure;
Xt = 20:20:120;
Xt_Offset = [-15,-10,-5,5,10,15];
for i=1:6
boxplot(GroupedData{i},'Color',DeviceColors{i});
set(gca,'XTick',Xt+Xt_Offset(i));
if i==3
set(gca,'XTickLabel',Speeds);
end
hold on;
end
xlabel('Speed');ylabel('Step Count'); grid on;
legend(legendEntries);
Any help would be appreciated!
I've made some modifications to your code. I've tested this in R2014b.
TreadmillData = randi([20,200],69,6);
Speeds = {'1.5mph' '2.5mph' '3.5mph' '4.5mph' '5.5mph' '6.5mph'};
DeviceColors = {'r' 'g' 'c' [0.5 0 0.5] 'b' [1 0.5 0]};
Pedometer1 = TreadmillData(1:7:end,:);
Pedometer2 = TreadmillData(2:7:end,:);
Pedometer3 = TreadmillData(3:7:end,:);
Pedometer4 = TreadmillData(4:7:end,:);
Pedometer5 = TreadmillData(5:7:end,:);
Pedometer6 = TreadmillData(6:7:end,:);
GroupedData = {Pedometer1 Pedometer2 Pedometer3 Pedometer4 Pedometer5 Pedometer6};
legendEntries = {'dev1' 'dev2' 'dev3' 'dev4' 'dev5' 'dev6'};
N = numel(GroupedData);
delta = linspace(-.3,.3,N); %// define offsets to distinguish plots
width = .2; %// small width to avoid overlap
cmap = hsv(N); %// colormap
legWidth = 1.8; %// make room for legend
figure;
hold on;
for ii=1:N %// better not to shadow i (imaginary unit)
%if ii~=ceil(N/2)
% labels = repmat({''},1,N); %// empty labels
%else
labels = Speeds; %// center plot: use real labels
%end
boxplot(GroupedData{ii},'Color', DeviceColors{ii}, 'boxstyle','filled', ...
'position',(1:numel(labels))+delta(ii), 'widths',width, 'labels',labels)
%// plot filled boxes with specified positions, widths, labels
plot(NaN,1,'color',DeviceColors{ii}); %// dummy plot for legend
end
xlabel('Speed'); ylabel('Step Count'); grid on;
xlim([1+2*delta(1) numel(labels)+legWidth+2*delta(N)]) %// adjust x limits, with room for legend
legend(legendEntries);
Here is a solution for plotting several boxplot. You have to group all the data in a single matrix, each group being separated by a column of Nan. After that, you can simply plot a single regular boxplot with ad-hoc options such as colors and labels.
The following example uses 2 groups of 3, so 7 columns. The 4 first lines of data:
0.6993 0.0207 -0.7485 NaN 0.5836 -0.1763 -1.8468
-0.0494 -1.5411 0.8022 NaN 2.7124 -0.0636 -2.3639
0.9134 0.7106 -0.1375 NaN -0.2200 -0.2528 -0.8350
-0.5655 1.3820 0.6038 NaN -0.7563 -0.9779 0.3789
And the code:
figure('Color', 'w');
c = colormap(lines(3));
A = randn(60,7); % some data
A(:,4) = NaN; % this is the trick for boxplot
C = [c; ones(1,3); c]; % this is the trick for coloring the boxes
% regular plot
boxplot(A, 'colors', C, 'plotstyle', 'compact', ...
'labels', {'','ASIA','','','','USA',''}); % label only two categories
hold on;
for ii = 1:3
plot(NaN,1,'color', c(ii,:), 'LineWidth', 4);
end
title('BOXPLOT');
ylabel('MPG');
xlabel('ORIGIN');
legend({'SUV', 'SEDAN', 'SPORT'});
set(gca, 'XLim', [0 8], 'YLim', [-5 5]);

How to change bars colour in MATLAB

I am new to programming so I am learning introductory to MATLAB I was wondering how you could change colours of bar in MATLAB.
this is my script. Can someone please help!!
x =[1:8]
for y = [20 30 40 50 60 70 80]
bar(x,y)
if y < 40
col = 'b';
else if y > 40
col= 'g';
end
end
end
i also tried bar(x,y, r) but it doesnt work
Whilst this is overkill for your specific question, in general, to change the colour of bars depending on their height, you can apply a colormap to the bars. This is mainly from the bar documentation.
x = 1:8;
y = 10*x;
h=bar(y); %// create a sample bar graph
For the colormap MAP, you do this:
colormap(MAP)
ch = get(h,'Children');
fvd = get(ch,'Faces');
fvcd = get(ch,'FaceVertexCData');
[zs, izs] = sort(y);
for i = 1:length(x)
row = izs(i);
fvcd(fvd(row,:)) = i;
end
set(ch,'FaceVertexCData',fvcd)
hold off
And, for example, using the builtin colormap hsv, you get
But in this case we want a very specific colormap,
b=40 %// the cut-off for changing the colour
MAP=zeros(length(x),3); %// intialise colormap matrix
MAP(y<b,:)=repmat([0 0 1],sum(y<b),1); %// [0 0 1] is blue, when y<40
MAP(y>=b,:)=repmat([0 1 0],sum(y>=b),1); %// [0 1 0] is green, for y>=40
colormap(MAP)
which gives
To use two different colors depending on y: compute a logical index depending on y values and call bar twice with appropriate arguments:
x = [1:8];
y = [20 30 40 50 60 70 80];
ind = y < 40; %// logical index
bar(x(ind), y(ind), 'facecolor', 'b', 'edgecolor', 'k') %// blue bars, black edge
hold on %// keep plot
bar(x(~ind), y(~ind), 'facecolor', 'g', 'edgecolor', 'k') %// green bars, black edge
set(gca,'xtick',x)
bar can take third argument, which is color value, e.g. bar(x,y, 'r').