Matlab;带有2个以上/拆分的图例R2017b的饼图

时间:2019-01-08 15:57:51

标签: matlab matlab-figure legend pie-chart

我正在创建一个饼图,理想情况下是希望图例在顶部和/或底部水平显示。但是,在几乎所有情况下,这都是不可能的,因为图例会消失。因此,理想情况下,我希望将图例分为两个(或更多)子图例,并将其分别放置。我知道这不是MATLAB的内置功能(我正在使用R2017b),但不确定是否可以使它正常工作?我见过一些人设法用折线图做类似的事情,但我无法使其适应我的饼图。

示例代码:

% Set up a figure and make it a reasonable size/location.
figure( 1 )
set( gcf, 'Position', [ 350, 150, 750, 750 ] )

% Create a list of items for the food menu (example only).
Menu = { "Egg and Bacon", "Egg, Sausage and becon", "Egg and Spam", ...
         "Egg, bacon and Spam", "Egg, bacon, sausage and Spam",     ...
         "Spam, bacon, sausage and Spam", "Nothing"                    };

% Estimate the demand for said food items (example only).
Orders = randi( 150, 1, length( Menu ) );

% Make a pie chart showing what ratio the food was ordered.
Pie_Plot = pie( Orders );

% Create two ranges to grab the first and second half of the pie chart's 
% patches.
Range_1 =                  1 : 2 : ceil( length( Pie_Plot ) / 2 );
Range_2 = Range_1( end ) + 2 : 2 : length( Pie_Plot );

% In an ideal world this would be the first of two legends that would 
% display at the same time.
Ideal_Leg_Pt1 = legend( Pie_Plot( Range_1 ), ...
        Menu( round( Range_1 / 2 ) ), 'orientation', 'horizontal', ...
        'location', 'southoutside'                                    );

% A pause because the method doesn't work so without it, this legend 
% won't appear.                         
pause

% The second half of the ideal legend(s) solution; noting that when this 
% is created, the original
% legend is replaced.
Ideal_Leg_Pt2 = legend( Pie_Plot( Range_2 ), ...
        Menu( round( Range_2 / 2) ), 'orientation', 'horizontal', ...
        'location', 'northoutside'                                   );

% Pause for the same reasons as before.
pause

% This is what I'm currently stuck with; a legend that doesn't fit (I'm 
% aware I could make it vertical for example but this looks messy in my 
% eyes and I'm trying to avoid it unless there really is no way to make 
% the ideal method work).
Current_Leg = legend( Menu, 'orientation', 'horizontal', ...
        'location', 'northoutside'                          );

编辑

已将其标记为可能的重复项,但我认为并非如此(但是我可能错了)。我已经看过与之链接的解决方案,但是这些解决方案在我的OP中通常都是类似的,但是我无法适应饼图。我可以接近(例如,zhqiat的方法),但是我不能完全使其适用于饼图。

在上述示例中,它通过绘制一些零件,创建新轴然后绘制其余部分来工作;但您无法使用饼图来做到这一点。我可以解决这个问题,但是最后我得到两个饼图,它们不能完全重叠。这就是为什么我不认为这是重复的问题的原因。饼形图似乎与常规图有本质上的区别,因此,许多似乎适用于常规线形图的解决方案似乎不适用于饼图(但是,我自由地承认,我只是忽略了一个简单的修改即可使其全部起作用! )。

上述示例的代码(直接放置在我的OP中的Ideal_Leg_Pt1下,其余所有内容都删除了)

ax2 = axes('Position',get(gca,'Position'),...
           'Visible','off','Color','none');

Second_Pie = pie( Orders );

Ideal_Leg_Pt2 = legend( Second_Pie( Range_2 ), ...
        Menu( round( Range_2 / 2) ), 'orientation', 'horizontal', ...
        'location', 'northoutside' );

2 个答案:

答案 0 :(得分:4)

此解决方案要求R2018a≥

将水平图例分为多列/行可能会达到目的,而不是使其复杂化。

legend(Menu, 'location', 'northoutside', 'orientation', 'horizontal', 'NumColumns', 3);

output

答案 1 :(得分:3)

您说您在2018a(2017b)之前具有Matlab版本,因此无法应用@Sardar's answer。因此,这是没有NumColumns属性的一种方法:

我们从代码的第一部分(与我的2017a兼容的版本)开始,在其中创建派,并放置图例的前半部分:

figure(1);
set(gcf,'Position',[350,150,750,750])
% Create a list of items for the food menu (example only).
Menu = {'Egg and Bacon', 'Egg, Sausage and becon', 'Egg and Spam', ...
         'Egg, bacon and Spam', 'Egg, bacon, sausage and Spam',     ...
         'Spam, bacon, sausage and Spam', 'Nothing'};
% Estimate the demand for said food items (example only).
Orders = randi(150,1,length(Menu));
% Make a pie chart showing what ratio the food was ordered.
Pie_Plot = pie(Orders);
% Create two ranges to grab the first and second half of the pie chart's 
% patches.
Range_1 = 1:2:ceil(length(Pie_Plot)/2);
Range_2 = Range_1(end)+2:2:length(Pie_Plot);

% In an ideal world this would be the first of two legends that would 
% display at the same time:
Ideal_Leg_Pt1 = legend(Pie_Plot(Range_1),Menu(round(Range_1/2)),...
    'orientation', 'horizontal','EdgeColor','none');

接下来,我们将手动设置Ideal_Leg_Pt1位置以获取一些空间:

Ideal_Leg_Pt1.Position(1:3) = [0 1-Ideal_Leg_Pt1.Position(4) 1];

现在,我们添加具有相同饼图的隐藏轴,但是这次添加图例的第二部分:

% the hidden axes are neded so the first legend won't be replaced:
hidden_ax = axes('Visible','off','NextPlot','add');
% we plot the same pie, only to create the objects in the legend:
Pie_Plot_2 = pie(Orders);
% The second half of the ideal legend(s) solution:
Ideal_Leg_Pt2 = legend(Pie_Plot_2(Range_2),Menu(round(Range_2/2)),...
    'orientation', 'horizontal','AutoUpdate','off',...
    'EdgeColor','none');

请注意,我们将Ideal_Leg_Pt2中的'AutoUpdate' property设置为'off',因此我们可以安全地删除虚拟派,而无需从图例中删除项目:

% remove the extra dummy pie:
Pie_Plot_2.delete

现在,我们可以相对于Ideal_Leg_Pt2的位置设置Ideal_Leg_Pt1的位置,以使它们看起来像一个图例:

% Define a position of the second legend to fit the first one:
% make the legend equally wide
Ideal_Leg_Pt2.Position([1 3]) = Ideal_Leg_Pt1.Position([1 3]);
% attach the two parts of the leggend
Ideal_Leg_Pt2.Position(2) = Ideal_Leg_Pt1.Position(2)-Ideal_Leg_Pt2.Position(4);

结果:

enter image description here

请注意,调整图的大小都需要重新设置图例,因此,如果出现问题,您可以设置图的'SizeChangedFcn'属性来为您完成此操作:

% updating the position of the legends upon resizing of the figure:
set(figure(1),'SizeChangedFcn',...
    ['Ideal_Leg_Pt1.Position(1:3) = [0 1-Ideal_Leg_Pt1.Position(4) 1];'...
     'Ideal_Leg_Pt2.Position([1 3]) = Ideal_Leg_Pt1.Position([1 3]);'...
     'Ideal_Leg_Pt2.Position(2) = Ideal_Leg_Pt1.Position(2)-Ideal_Leg_Pt2.Position(4);']);

或设置一个小功能来将其保存在其他M文件中:

function setLgePos(Ideal_Leg_Pt1,Ideal_Leg_Pt2)
Ideal_Leg_Pt1.Position(1:3) = [0 1-Ideal_Leg_Pt1.Position(4) 1];
Ideal_Leg_Pt2.Position([1 3]) = Ideal_Leg_Pt1.Position([1 3]);
Ideal_Leg_Pt2.Position(2) = Ideal_Leg_Pt1.Position(2)-Ideal_Leg_Pt2.Position(4);
end

并从Figure属性调用它:

set(figure(1),'SizeChangedFcn','setLgePos(Ideal_Leg_Pt1,Ideal_Leg_Pt2)');