软件;带有 2+ 个/拆分图例的饼图 R2017b
Matlab; Pie chart with 2+ / split legends R2017b
我正在创建饼图,理想情况下希望图例水平显示在顶部 and/or 底部。然而,在几乎所有情况下,这都是不可能的,因为图例已经消失了。因此,理想情况下,我想将图例分成两个(或更多)子图例并将它们单独放置。我知道这不是 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' );
此解决方案需要 ≥ R2018a
不要让它复杂化,将水平图例分成多个columns/rows可能会达到你的目的。
legend(Menu, 'location', 'northoutside', 'orientation', 'horizontal', 'NumColumns', 3);
你说你有 2018a (2017b) 之前的 Matlab 版本,因此你不能申请 。所以这是一种没有 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
位置以获得一些 space:
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);
结果:
请注意,任何调整图形大小都需要重新定位图例,因此如果这是一个问题,您可以设置图形的 '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
并从图中调用属性:
set(figure(1),'SizeChangedFcn','setLgePos(Ideal_Leg_Pt1,Ideal_Leg_Pt2)');
我正在创建饼图,理想情况下希望图例水平显示在顶部 and/or 底部。然而,在几乎所有情况下,这都是不可能的,因为图例已经消失了。因此,理想情况下,我想将图例分成两个(或更多)子图例并将它们单独放置。我知道这不是 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' );
此解决方案需要 ≥ R2018a
不要让它复杂化,将水平图例分成多个columns/rows可能会达到你的目的。
legend(Menu, 'location', 'northoutside', 'orientation', 'horizontal', 'NumColumns', 3);
你说你有 2018a (2017b) 之前的 Matlab 版本,因此你不能申请 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
位置以获得一些 space:
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);
结果:
请注意,任何调整图形大小都需要重新定位图例,因此如果这是一个问题,您可以设置图形的 '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
并从图中调用属性:
set(figure(1),'SizeChangedFcn','setLgePos(Ideal_Leg_Pt1,Ideal_Leg_Pt2)');