Changing the marker shape or aspect ratio in a legend

Consider the following example code, and the plot legend it creates:
% Example data
means = [10 40 50 60; ...3 groups, each with 4 conditions (measures)
20 50 60 70; ...
30 60 80 90];
SEMs = [1 4 8 6; ...
2 5 9 12; ...
3 6 10 13];
nGroups = size(means, 1);
nConditionsPerGroup = size(means, 2);
figure('Position', [71 433 560 420])
b = bar(means, 'grouped');
hold on
clear x
% Get the x coordinate of the bars
for i = 1:nConditionsPerGroup
x(i,:) = b(i).XEndPoints;
b(i).BarWidth = 1;
end
% Plot the errorbars
errorbar(x',means,SEMs,'k','linestyle','none');
hold off
set(gca, 'XTickLabel', {'Low' 'Middle' 'High'}, 'FontSize', 12);
xlabel('Socio-economic status', 'FontSize', 18)
[leg,att] = legend('A', 'B', 'C', 'D', 'Orientation','horizontal', 'FontSize', 15);
title(leg,'Measures')
leg.Title.Visible = 'off';
box off
ax = gca;
ax.YGrid = 'on';
I'd like to change the aspect ratio of the legend markers to make them square instead of rectangular. Alternatively, to change their shape altogether and make them e.g. round.
However, I found no property inside the legend handle to manipulate aspect ratio or shape of the markers, only their size (`MarkerSize`). Changing the overall size (width/height) of the legend leaves aspect ratio unchanged.
Thanks for any help!

 Akzeptierte Antwort

DGM
DGM am 20 Jun. 2023
Bearbeitet: DGM am 20 Jun. 2023
Here's one way. You might also want to adjust the text object positions as well.
% Example data
means = [10 40 50 60; ...3 groups, each with 4 conditions (measures)
20 50 60 70; ...
30 60 80 90];
SEMs = [1 4 8 6; ...
2 5 9 12; ...
3 6 10 13];
nGroups = size(means, 1);
nConditionsPerGroup = size(means, 2);
%figure('Position', [71 433 560 420])
b = bar(means, 'grouped');
hold on
clear x
% Get the x coordinate of the bars
for i = 1:nConditionsPerGroup
x(i,:) = b(i).XEndPoints;
b(i).BarWidth = 1;
end
% Plot the errorbars
errorbar(x',means,SEMs,'k','linestyle','none');
hold off
set(gca, 'XTickLabel', {'Low' 'Middle' 'High'}, 'FontSize', 12);
xlabel('Socio-economic status', 'FontSize', 18)
[leg,att] = legend('A', 'B', 'C', 'D', 'Orientation','horizontal', 'FontSize', 15);
title(leg,'Measures')
leg.Title.Visible = 'off';
box off
ax = gca;
ax.YGrid = 'on';
% adjust each patch object in the legend
% patch vertex data is normalized WRT the legend box
textoffset = att(1).Position(1) - att(5).Children.Vertices(3,1);
leg.Units = 'pixels';
lp = leg.Position;
for k = 1:4
V = att(k+4).Children.Vertices;
xcent = mean(V(2:3,1))*lp(3);
halfw = diff(V(1:2,2))/2*lp(4);
V(:,1) = (xcent + halfw*[-1 -1 1 1 -1].')/lp(3);
att(k+4).Children.Vertices = V;
att(k).Position(1) = V(3,1) + textoffset;
end
Since the objects are just patches, I don't see why you couldn't make them into any polygonal shape you want.
Alternatively, you can also do other workarounds using dummy objects:

3 Kommentare

z8080
z8080 am 21 Jun. 2023
Bearbeitet: z8080 am 21 Jun. 2023
thank you! would making markers round be possible too, given that circles are not polygons?
As far as anyone will be able to tell, an appropriate polygon might as well be a circle.
% Example data
means = [10 40 50 60; ...3 groups, each with 4 conditions (measures)
20 50 60 70; ...
30 60 80 90];
SEMs = [1 4 8 6; ...
2 5 9 12; ...
3 6 10 13];
nGroups = size(means, 1);
nConditionsPerGroup = size(means, 2);
%figure('Position', [71 433 560 420])
b = bar(means, 'grouped');
hold on
clear x
% Get the x coordinate of the bars
for i = 1:nConditionsPerGroup
x(i,:) = b(i).XEndPoints;
b(i).BarWidth = 1;
end
% Plot the errorbars
errorbar(x',means,SEMs,'k','linestyle','none');
hold off
set(gca, 'XTickLabel', {'Low' 'Middle' 'High'}, 'FontSize', 12);
xlabel('Socio-economic status', 'FontSize', 18)
[leg,att] = legend('A', 'B', 'C', 'D', 'Orientation','horizontal', 'FontSize', 15);
title(leg,'Measures')
leg.Title.Visible = 'off';
box off
ax = gca;
ax.YGrid = 'on';
% adjust each patch object in the legend
% patch vertex data is normalized WRT the legend box
nsides = 100; % pick any regular polygon
theta = (0:360/nsides:360) + 360/nsides/2;
textoffset = att(1).Position(1) - att(5).Children.Vertices(3,1);
leg.Units = 'pixels';
lp = leg.Position;
for k = 1:4
% replace patch object with a regular polygon
V = att(k+4).Children.Vertices;
patchcent = [mean(V(2:3,1)) mean(V(1:2,2))].*lp(3:4);
radius = diff(V(1:2,2))/2*lp(4);
V = patchcent + radius*[cosd(theta.') sind(theta.')];
V = V./lp(3:4);
att(k+4).Children.Vertices = V;
att(k+4).Children.Faces = 1:numel(theta);
% move text label
att(k).Position(1) = V(3,1) + textoffset;
end
beautiful work!!

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (0)

Kategorien

Mehr zu Data Distribution Plots finden Sie in Hilfe-Center und File Exchange

Produkte

Version

R2023a

Tags

Gefragt:

am 20 Jun. 2023

Kommentiert:

am 22 Jun. 2023

Community Treasure Hunt

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

Start Hunting!

Translated by