Reputation: 626
I would like to generate a plot which contains both lines (plot
, stairs
) and bars (bar
). For plot
and stairs
, I usually use 'DisplayName'
property to generate the legend. With a stacked bar
plot, this does not seem to work anymore. Consider this MWE:
x_max = 20;
results = [3 37 50; 7 27 25; 11 0 13; 18 45 0];
figure('Position', [470 430 1000 600]);
plot(0:x_max, polyval([3 1], 0:x_max), 'DisplayName', 'Production rate');
hold on; grid on;
bh = bar(results(:,1), results(:,2:3), 0.2, 'stacked', 'DisplayName', 'Fraction');
xlim([0 x_max]);
legend('Location', 'best');
set(gca, 'FontSize', 18);
hold off
I would like to get a custom legend entry for each of the two fractions, e.g., 'Fraction1', 'Fraction2'
. However, both variantes produce an error:
bar(results(:,1), results(:,2:3), 0.2, 'stacked', 'DisplayName', 'Fraction1', 'Fraction2')
bar(results(:,1), results(:,2:3), 0.2, 'stacked', 'DisplayName', {'Fraction1', 'Fraction2'})
>>Error setting property 'DisplayName' of class 'Bar':
Value must be a character vector or string scalar.
But if I do
bh.get('DisplayName')
I get
ans =
2×1 cell array
{'getcolumn(Fraction,1)'}
{'getcolumn(Fraction,2)'}
Which means that Matlab internally does generate a cell array for the 'DisplayName'
, but does not let me assign one. This fails:
bh.set('DisplayName', {'Fraction1'; 'Fraction2'})
I know I could edit the cell array of legend entries directly, but I prefer the 'DisplayName'
, since the legend entries never get out of order when I change the plot commands (or add or delete any of them). Any solution?
Upvotes: 4
Views: 215
Reputation: 30047
As a quick workaround, you could set each bar object's DisplayName
after creation.
See this solution which builds on your example:
The issue you're having is that the stacked bar
creates a Bar
array (in this case 1x2). You can't set the DisplayName
property of the Bar
array, you need to set the property of each Bar
in the array.
% Your example code, without trying to set bar display names
x_max = 20;
results = [3 37 50; 7 27 25; 11 0 13; 18 45 0];
figure('Position', [470 430 1000 600]);
plot(0:x_max, polyval([3 1], 0:x_max), 'DisplayName', 'Production rate');
hold on; grid on;
bh = bar(results(:,1), results(:,2:3), 0.2, 'stacked');
xlim([0 x_max]);
legend('Location', 'best');
set(gca, 'FontSize', 18);
hold off
% Set bar names
names = {'Fraction1'; 'Fraction2'};
for n = 1:numel(names)
set( bh(n), 'DisplayName', names{n} );
end
You can do this without the loop, at the cost of slightly less explicit syntax:
names = {'Fraction1'; 'Fraction2'};
[bh(:).DisplayName] = names{:};
Upvotes: 3