Changing the marker shape or aspect ratio in a legend

14 vues (au cours des 30 derniers jours)
z8080
z8080 le 20 Juin 2023
Commenté : z8080 le 22 Juin 2023
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!

Réponse acceptée

DGM
DGM le 20 Juin 2023
Modifié(e) : DGM le 20 Juin 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 commentaires
DGM
DGM le 22 Juin 2023
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
z8080
z8080 le 22 Juin 2023
beautiful work!!

Connectez-vous pour commenter.

Plus de réponses (0)

Tags

Produits


Version

R2023a

Community Treasure Hunt

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

Start Hunting!

Translated by