Legend in multiple plots: example bubblecharts or combined plot bubblechart and scatter

18 views (last 30 days)
Hi, I am trying to display to variables on a map and add a legend for both of the variables. Since I the problems is the legend I removed the map behind the plot to just focus on the variables.
I splitted the two variables first in two seperate plots to show how the legend should look like for each variable. Than I combine it in two ways and discuss the legend problems that I have face.
% create random data
xCoordinate = randi([3.1976e+05 8.2960e+05],21, 1); %Location on a map xCoordinate
yCoordinate = randi([6.1639e+06 7.2924e+06],21, 1); %Location on a map yCoordinate
markerSizesV = randi([0 5],21, 1);
markerSizesC = randi([1 379],21, 1);
%% create bubblechart Cats per km^2 of region with legend
bC = bubblechart(xCoordinate,yCoordinate,markerSizesC, [1, 1, 1]); %FaceColor white
bC.MarkerEdgeColor = [0,0,0]; %EdgeColor black
bubblesize([4 15]) % limit the bubblesize
axis equal % ensures 1 unit in x equals 1 unit in y
axis off % romoves the axis
blgdC1 = bubblelegend({'Cats';'per km^2'},'Location','eastoutside'); % plots the legend
The legend for Cats per km^2 should look like in the plot above. (Ignor the that some of the bubbles are getting cut off this doesn't happens when the map is ploted as well.)
%% create bubblechart Cat visits per region with legend
bV = bubblechart(xCoordinate,yCoordinate,markerSizesV, [0.9290, 0.6940, 0.1250]);
bubblesize([4 15])
axis equal % ensures 1 unit in x equals 1 unit in y
axis off
blgdV1 = bubblelegend({'Cat Visits';'per region'});
The legend for Cat visits per region should look like in the plot above. (Ignor the that some of the bubbles are getting cut off this doesn't happens when the map is ploted as well.)
%% combined bubblechart Cats per km^2 and Cat visits per region
bC = bubblechart(xCoordinate,yCoordinate,markerSizesC, [1, 1, 1]);
hold on
bC.MarkerEdgeColor = [0,0,0];
bubblesize([4 15])
axis equal % ensures 1 unit in x equals 1 unit in y
axis off
bV = bubblechart(xCoordinate,yCoordinate,markerSizesV, [0.9290, 0.6940, 0.1250]);
bubblesize([4 15])
blgdC2 = bubblelegend({'Cats';'per km^2'},'Location','eastoutside'); %
blgdV2 = bubblelegend({'Cat Visits';'per region'},'Location','westoutside');
legend('Cats per km^2', 'Cat Visits per Region') %test what legend does
hold off
As soon as I combine two bubblecharts MATLAB combines valus in ratio to each other and combines it also into the same population legend. This is fine if I would have two variables with the same unit / content but different regions.
Therefore I tryed a version with
%% combine bubblechart Cat visits per region with scatter Cats per km^2
s = scatter(xCoordinate,yCoordinate,markerSizesC/2, MarkerFaceColor = "white", MarkerEdgeColor = "#36454F");
hold on
bV = bubblechart(xCoordinate,yCoordinate,markerSizesV, [0.9290, 0.6940, 0.1250]);
bubblesize([4 15])
axis equal % ensures 1 unit in x equals 1 unit in y
axis off
blgdV = bubblelegend({'Cat Visits';'per region'},'Location','westoutside');
legend('Cats per km^2', 'Cat Visits per Region')
hold off
This solves at least the problem that MATLAB considers these two variables should be in relation to each other. Plus the legend for "Cat visits per region" is correct and with the right color and right size.
However I don't get a legend like this next to my plot as in the bubblechart combinded with scatter.
Is their anyone knowing how to solve this issue with legends?
Thanks for any input in this matter.
  2 Comments
dpb
dpb on 11 Sep 2025
Use a tiledlayout of 1,1 tiling to overlay the two in order to keep them separate. There's <an example> bubblechart that is similar that should give you the idea.
Désirée Kroner
Désirée Kroner on 15 Sep 2025
Edited: Désirée Kroner on 15 Sep 2025
Thanks for the hint with the tiledlayout. But unfortnatly it does the same. It summerizes the values into one bubblelegend and legend.
% create random date for the plot
xCoordinate = randi([3.1976e+05 8.2960e+05],21, 1); %Location on a map xCoordinate
yCoordinate = randi([6.1639e+06 7.2924e+06],21, 1); %Location on a map yCoordinate
markerSizesV = randi([0 5],21, 1);
markerSizesC = randi([1 379],21, 1);
%% combined bubblechart Cats per km^2 and Cat visits per region
t = tiledlayout(1,1);
nexttile;
bV = bubblechart(xCoordinate,yCoordinate,markerSizesV, [0.9290, 0.6940, 0.1250]);
bubblesize([4 15])
hold on
axis equal % ensures 1 unit in x equals 1 unit in y
axis off
bC = bubblechart(xCoordinate,yCoordinate,markerSizesC, [1, 1, 1]);
bC.MarkerEdgeColor = [0,0,0];
bubblesize([4 15])
blgdV3 = bubblelegend({'Cat Visits';'per region'},'Location','westoutside');
blgdC3 = bubblelegend({'Cats';'per km^2'},'Location','eastoutside'); %
legend('Cats per km^2', 'Cat Visits per Region') %test what legend does
hold off

Sign in to comment.

Accepted Answer

Shantanu
Shantanu on 15 Sep 2025
Hi Désirée Kroner,
The “bubblelegend” function only supports one bubble chart at a time, causing issues when multiple are present. Your solution to combine a “scatter" plot for one variable and a “bubblechart” for the other is correct. This separates the data scaling. The solution for the legends is to build two custom ones manually.
This is done by creating a small, separate axes object on your figure and then drawing the legend elements inside it.
Here is an example code for this
clear; clc; close all;
rng(1);
xCoordinate = randi([3.1976e+05 8.2960e+05],21, 1);
yCoordinate = randi([6.1639e+06 7.2924e+06],21, 1);
markerSizesV = randi([0 5],21, 1);
markerSizesC = randi([36 379],21, 1);
figure('Position', [100, 100, 900, 550]);
ax_main = axes('Position', [0.35, 0.1, 0.6, 0.8]);
hold(ax_main, 'on');
s = scatter(ax_main, xCoordinate, yCoordinate, markerSizesC, 'MarkerFaceColor', 'white', 'MarkerEdgeColor', 'black');
bV = bubblechart(ax_main, xCoordinate, yCoordinate, markerSizesV, [0.9290, 0.6940, 0.1250]);
bubblesize(ax_main, [4, 15]);
axis(ax_main, 'equal');
axis(ax_main, 'off');
% --- 3. Create Two Custom Legends ---
pos_Lgd1 = [0.05, 0.3, 0.12, 0.4];
pos_Lgd2 = [0.18, 0.3, 0.12, 0.4];
% --- Create the FIRST Custom Legend ('Cats per km^2') ---
ax_lgd_C = axes('Position', pos_Lgd1);
hold(ax_lgd_C, 'on');
lgd_C_title = {'Cats'; 'per km^2'};
text(1.25, 0.95, lgd_C_title, 'HorizontalAlignment', 'center', 'FontWeight', 'bold', 'VerticalAlignment', 'top');
plot([0.8, 1.7], [0.88, 0.88], 'k-');
lgd_C_values = [min(markerSizesC), round(mean(markerSizesC)), max(markerSizesC)];
lgd_C_bubblesizes = lgd_C_values;
y_positions = [0.15, 0.425, 0.7];
scatter(ax_lgd_C, ones(1,3)*1.1, y_positions, lgd_C_bubblesizes, 'MarkerFaceColor', 'white', 'MarkerEdgeColor', 'black', 'LineWidth', 1);
text(ax_lgd_C, 1.4, y_positions(1), num2str(lgd_C_values(1)), 'VerticalAlignment', 'middle');
text(ax_lgd_C, 1.4, y_positions(3), num2str(lgd_C_values(3)), 'VerticalAlignment', 'middle');
plot(ax_lgd_C, [1.1, 1.1], [y_positions(1), y_positions(3)], 'k-');
set(ax_lgd_C, 'Color', 'white', 'Box', 'on', 'XTick', [], 'YTick', []);
ylim([0, 1]);
xlim([0.8, 1.7]);
% --- Create the SECOND Custom Legend ('Cat Visits') ---
ax_lgd_V = axes('Position', pos_Lgd2);
hold(ax_lgd_V, 'on');
lgd_V_title = {'Cat Visits'; 'per region'};
text(1.25, 0.95, lgd_V_title, 'HorizontalAlignment', 'center', 'FontWeight', 'bold', 'VerticalAlignment', 'top');
plot([0.8, 1.7], [0.88, 0.88], 'k-');
lgd_V_values = [min(markerSizesV), round(mean(markerSizesV)), max(markerSizesV)];
lgd_V_bubblesizes = [40, 80, 120];
y_positions = [0.15, 0.425, 0.7];
scatter(ax_lgd_V, ones(1,3)*1.1, y_positions, lgd_V_bubblesizes, 'MarkerFaceColor', [0.9290, 0.6940, 0.1250], 'MarkerEdgeColor', 'none');
text(ax_lgd_V, 1.4, y_positions(1), num2str(lgd_V_values(1)), 'VerticalAlignment', 'middle');
text(ax_lgd_V, 1.4, y_positions(3), num2str(lgd_V_values(3)), 'VerticalAlignment', 'middle');
plot(ax_lgd_V, [1.1, 1.1], [y_positions(1), y_positions(3)], 'k-');
set(ax_lgd_V, 'Color', 'white', 'Box', 'on', 'XTick', [], 'YTick', []);
ylim([0, 1]);
xlim([0.8, 1.7]);
hold(ax_main, 'off');
Please adjust the legends styling accordingly. For more information refer to the following MATLAB documentations
  1 Comment
Désirée Kroner
Désirée Kroner on 15 Sep 2025
Hi Shantanu
Many thanks for this inspiration, I learned a lot about creating custom legends.
Here is my adapted version
clear; clc; close all;
rng(1);
xCoordinate = randi([3.1976e+05 8.2960e+05],21, 1);
yCoordinate = randi([6.1639e+06 7.2924e+06],21, 1);
markerSizesV = randi([0 5],21, 1);
markerSizesC = randi([36 379],21, 1);
figure('Position', [100, 100, 900, 550]);
ax_main = axes('Position', [0.1, 0.1, 0.6, 0.8]);
hold(ax_main, 'on');
s = scatter(ax_main, xCoordinate, yCoordinate, markerSizesC/2, 'MarkerFaceColor', 'white', 'MarkerEdgeColor', 'black');
bV = bubblechart(ax_main, xCoordinate, yCoordinate, markerSizesV, [0.9290, 0.6940, 0.1250]);
bubblesize(ax_main, [4, 15]);
axis(ax_main, 'equal');
axis(ax_main, 'off');
% --- 3. Create Two Custom Legends ---
pos_Lgd1 = [0.6, 0.61, 0.11, 0.3]; %% x-coordinate ,y-coordinate, width, hight
pos_Lgd2 = [0.6, 0.3, 0.11, 0.3];
% --- Create the FIRST Custom Legend ('Cats per km^2') ---
ax_lgd_C = axes('Position', pos_Lgd1);
hold(ax_lgd_C, 'on');
lgd_C_title = {'Cats'; 'per km^2'};
text(1.25, 0.95, lgd_C_title, 'HorizontalAlignment', 'center', 'FontWeight', 'bold', 'VerticalAlignment', 'top');
plot([0.8, 1.7], [0.7, 0.7], 'k-'); %% horizonel line seperator [x1, x2], [y1,y2]
lgd_C_values = [min(markerSizesC), round(mean(markerSizesC)), max(markerSizesC)];
lgd_C_bubblesizes = lgd_C_values;
y_positions = [0.1, 0.325, 0.55];
scatter(ax_lgd_C, ones(1,3)*1.1, y_positions, lgd_C_bubblesizes/2, 'MarkerFaceColor', 'white', 'MarkerEdgeColor', 'black', 'LineWidth', 0.5); %LineWidth 0.5 as in scatter plot
text(ax_lgd_C, 1.4, y_positions(1), num2str(lgd_C_values(1)), 'VerticalAlignment', 'middle');
text(ax_lgd_C, 1.4, y_positions(3), num2str(lgd_C_values(3)), 'VerticalAlignment', 'middle');
plot(ax_lgd_C, [1.25, 1.25], [y_positions(1), y_positions(3)], 'k-');
plot(ax_lgd_C, [1.25, 1.35], [y_positions(1), y_positions(1)],'k-');
plot(ax_lgd_C, [1.25, 1.35], [y_positions(3), y_positions(3)],'k-');
set(ax_lgd_C, 'Color', 'white', 'Box', 'on', 'XTick', [], 'YTick', []);
ylim([0, 1]);
xlim([0.8, 1.7]);
% --- Create the SECOND Custom Legend ('Cat Visits') ---
ax_lgd_V = axes('Position', pos_Lgd2);
hold(ax_lgd_V, 'on');
lgd_V_title = {'Cat Visits'; 'per region'};
text(1.25, 0.95, lgd_V_title, 'HorizontalAlignment', 'center', 'FontWeight', 'bold', 'VerticalAlignment', 'top');
plot([0.8, 1.7], [0.7, 0.7], 'k-');
lgd_V_values = [min(markerSizesV), round(mean(markerSizesV)), max(markerSizesV)];
lgd_V_bubblesizes = [40, 100, 180];
y_positions = [0.1, 0.325, 0.55];
s=scatter(ax_lgd_V, ones(1,3)*1.1, y_positions, lgd_V_bubblesizes, 'MarkerFaceColor', [0.9290, 0.6940, 0.1250], 'MarkerEdgeColor', 'none');
s.MarkerFaceAlpha = 0.6; % transparency as in bubblechart
text(ax_lgd_V, 1.4, y_positions(1), num2str(lgd_V_values(1)), 'VerticalAlignment', 'middle');
text(ax_lgd_V, 1.4, y_positions(3), num2str(lgd_V_values(3)), 'VerticalAlignment', 'middle');
plot(ax_lgd_V, [1.25, 1.25], [y_positions(1), y_positions(3)], 'k-');
plot(ax_lgd_V, [1.25, 1.35], [y_positions(1), y_positions(1)],'k-');
plot(ax_lgd_V, [1.25, 1.35], [y_positions(3), y_positions(3)],'k-');
set(ax_lgd_V, 'Color', 'white', 'Box', 'on', 'XTick', [], 'YTick', []);
ylim([0, 1]);
xlim([0.8, 1.7]);
hold(ax_main, 'off');

Sign in to comment.

More Answers (0)

Categories

Find more on Labels and Annotations in Help Center and File Exchange

Products


Release

R2025a

Community Treasure Hunt

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

Start Hunting!