No API supports functions `bar` and `legend` in multi-figure

1 view (last 30 days)
clear, close all
x1 = rand(1,18);
x2 = rand(1,18);
x3 = rand(1,18);
x4 = rand(1,18);
myLegends = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R"};
colors = rand(18,3);
t = tiledlayout('flow', 'TileSpacing', 'compact');
nexttile
b1 = bar(x1);
b1.FaceColor = 'flat';
for i = 1:length(colors)
b1.CData(i,:) = colors(i,:);
end
set(gca,'XTickLabel',[]);
nexttile
b2 = bar(x2);
b2.FaceColor = 'flat';
for i = 1:length(colors)
b2.CData(i,:) = colors(i,:);
end
set(gca,'XTickLabel',[]);
nexttile
b3 = bar(x3);
b3.FaceColor = 'flat';
for i = 1:length(colors)
b3.CData(i,:) = colors(i,:);
end
set(gca,'XTickLabel',[]);
nexttile
b4 = bar(x4);
b4.FaceColor = 'flat';
for i = 1:length(colors)
b4.CData(i,:) = colors(i,:);
end
set(gca,'XTickLabel',[]);
lgd = legend(myLegends);
Warning: Ignoring extra legend entries.
lgd.Layout.Tile = 'east';
i'd like to create a legend on the right, and the legend should contains 18 labels corresponding to the colors. i tried my best but failed.
The main reason is that the bar function does not support individual bars forming a group, resulting in the legend function not being able to recognize bars of different colors.
The second reason lies in that `legend` function does not support custom creation, that is, creating with preset colors and labels from the scratch.
Call on developers to make improvements.

Accepted Answer

Benjamin Kraus
Benjamin Kraus on 21 Jun 2023
Edited: Benjamin Kraus on 21 Jun 2023
You can only have one legend entry per bar object, and each of your calls to the bar command creates only one bar object.
You have two options:
Option 1: Multiple calls to bar
@Vishnu is on the right track with the first option (which is to call the bar command multiple times), but left out the x-data when calling the bar command:
x1 = rand(1,18);
x2 = rand(1,18);
x3 = rand(1,18);
x4 = rand(1,18);
myLegends = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R"};
colors = rand(18,3);
t = tiledlayout('flow', 'TileSpacing', 'compact');
nexttile
b1 = bar(1, x1(1),'FaceColor',colors(1,:));
hold on
for i = 2:height(colors)
b1(i) = bar(i, x1(i), 'FaceColor',colors(i,:));
end
xticks auto
nexttile
b2 = bar(1, x2(1),'FaceColor',colors(1,:));
hold on
for i = 2:height(colors)
b2(i) = bar(i, x2(i), 'FaceColor',colors(i,:));
end
xticks auto
nexttile
b3 = bar(1, x3(1),'FaceColor',colors(1,:));
hold on
for i = 2:height(colors)
b3(i) = bar(i, x3(i), 'FaceColor',colors(i,:));
end
xticks auto
nexttile
b4 = bar(1, x4(1),'FaceColor',colors(1,:));
hold on
for i = 2:height(colors)
b4(i) = bar(i, x4(i), 'FaceColor',colors(i,:));
end
xticks auto
lgd = legend(b4, myLegends);
lgd.Layout.Tile = 'east';
Option 2: Use a diagonal matrix
This version produces the same results as the above, but it cheats a little and uses a diagonal matrix to do it.
figure
t = tiledlayout('flow', 'TileSpacing', 'compact');
nexttile
x1Mat = diag(x1);
b1 = bar(x1Mat,'stacked');
for i = 1:numel(b1)
b1(i).FaceColor = colors(i,:);
end
set(gca,'XTickLabel',[]);
nexttile
x2Mat = diag(x2);
b2 = bar(x2Mat,'stacked');
for i = 1:numel(b2)
b2(i).FaceColor = colors(i,:);
end
set(gca,'XTickLabel',[]);
nexttile
x3Mat = diag(x3);
b3 = bar(x1Mat,'stacked');
for i = 1:numel(b3)
b3(i).FaceColor = colors(i,:);
end
set(gca,'XTickLabel',[]);
nexttile
x4Mat = diag(x4);
b4 = bar(x4Mat,'stacked');
for i = 1:numel(b4)
b4(i).FaceColor = colors(i,:);
end
set(gca,'XTickLabel',[]);
lgd = legend(b4, myLegends);
lgd.Layout.Tile = 'east';
  1 Comment
Yihang Xu
Yihang Xu on 21 Jun 2023
Thanks a lot. Option 1 works well.
i have thought about the option 2,but did not make this trade-off.

Sign in to comment.

More Answers (1)

Vishnu
Vishnu on 21 Jun 2023
Hi Yihang,
It looks like you are trying to create a bar plot with individual colors for each bar and add a legend to it. Unfortunately, the legend function won't be able to recognize bars with different colors when they are created separately using the bar function.
However, you can create the legend manually using a loop to plot each color with its corresponding label. Here is the code ,
clear, close all
x1 = rand(1,18);
x2 = rand(1,18);
x3 = rand(1,18);
x4 = rand(1,18);
myLegends = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R"};
colors = rand(18,3);
t = tiledlayout('flow', 'TileSpacing', 'compact');
nexttile
b1 = bar(x1,'FaceColor',colors(1,:));
set(gca,'XTickLabel',[]);
hold on;
for i = 2:length(colors)
tempbar = bar(x1(i),'FaceColor',colors(i,:));
end
nexttile
b2 = bar(x2,'FaceColor',colors(1,:));
set(gca,'XTickLabel',[]);
hold on;
for i = 2:length(colors)
tempbar = bar(x2(i),'FaceColor',colors(i,:));
end
nexttile
b3 = bar(x3,'FaceColor',colors(1,:));
set(gca,'XTickLabel',[]);
hold on;
for i = 2:length(colors)
tempbar = bar(x3(i),'FaceColor',colors(i,:));
end
nexttile
b4 = bar(x4,'FaceColor',colors(1,:));
set(gca,'XTickLabel',[]);
hold on;
for i = 2:length(colors)
tempbar = bar(x4(i),'FaceColor',colors(i,:));
end
lgd = legend(myLegends,'Location','east');
lgd.String = {}; % clear existing legend strings
for i = 1:length(myLegends)
l(i) = line(nan, nan, 'LineWidth', 10, 'Color', colors(i,:));
lgd.String{i} = myLegends{i};
end
% you can move the lengend by dragging it, after running in MATLAB.
  1 Comment
Yihang Xu
Yihang Xu on 21 Jun 2023
The results does not meet my expectations. However, i am inspired by it to write this code, just modify a number from 1 to 2
clear, close all
x1 = rand(1,18);
x2 = rand(1,18);
x3 = rand(1,18);
x4 = rand(1,18);
myLegends = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R"};
colors = rand(18,3);
t = tiledlayout('flow', 'TileSpacing', 'compact');
nexttile
b1 = bar(x1);
b1.FaceColor = 'flat';
for i = 1:length(colors)
b1.CData(i,:) = colors(i,:);
end
set(gca,'XTickLabel',[]);
nexttile
b2 = bar(x2);
b2.FaceColor = 'flat';
for i = 1:length(colors)
b2.CData(i,:) = colors(i,:);
end
set(gca,'XTickLabel',[]);
nexttile
b3 = bar(x3);
b3.FaceColor = 'flat';
for i = 1:length(colors)
b3.CData(i,:) = colors(i,:);
end
set(gca,'XTickLabel',[]);
nexttile
b4 = bar(x4);
b4.FaceColor = 'flat';
for i = 1:length(colors)
b4.CData(i,:) = colors(i,:);
end
set(gca,'XTickLabel',[]);
lgd = legend(myLegends);
Warning: Ignoring extra legend entries.
lgd.Layout.Tile = 'east';
lgd.String = {}; % clear existing legend strings
for i = 2:length(myLegends)
l(i) = line(nan, nan, 'LineWidth', 10, 'Color', colors(i,:));
lgd.String{i} = myLegends{i};
end

Sign in to comment.

Categories

Find more on Data Distribution Plots in Help Center and File Exchange

Products


Release

R2023a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!