Matlab:更改图例中条目的顺序
Posted
技术标签:
【中文标题】Matlab:更改图例中条目的顺序【英文标题】:Matlab: change order of entries in Figure legend 【发布时间】:2016-12-30 10:25:23 【问题描述】:我有一个图形文件,我想在其中更改条目的顺序(例如,将第一个条目作为第三个条目)。我很久以前保存了这个Figure.fig,所以我不确定我是否可以恢复原始代码。
在这里我向你展示我的情节:
我希望图例元素按降序排列(如图所示),但由于一个错误,我的第二个条目指的是错误的情节(上面写着“25 年”,但情节实际上指的是最低的趋势,对应“9年”趋势)。
我可以直接从Matlab中图形的属性编辑器切换图例中条目的顺序吗?如果是,如何(我没有看到任何“订单”属性或类似属性)?否则有没有其他简单的方法来切换图例中的条目顺序?
【问题讨论】:
如果你加载图,你不能用新的条目顺序再次执行legend
吗?
什么版本的 MATLAB?
是Matlab R2015b
该图是否也在 R2015b 中生成?
是的,我很确定
【参考方案1】:
如果您的图形是在 R2014b 或更新版本中生成的,您可以利用未记录的 'PlotChildren'
属性来操作图例条目的顺序,而无需调用新的 legend
。
例如:
x = 1:10;
y1 = x;
y2 = 2*x;
y3 = 3*x;
y4 = x.^2;
plot(x, y1, x, y2, x, y3, x, y4);
lh = legend('y = x', 'y = 2*x', 'y = 3*x', 'y = x.^2');
生产:
然后您可以对其进行操作:
neworder = [3, 1, 4, 2];
lh.PlotChildren = lh.PlotChildren(neworder);
制作:
如果您没有 legend
对象的句柄,则它是 figure
对象的子对象,其中包含绘制数据的 axes
对象。您可以使用以下findobj
方法之一找到您的legend
对象的句柄:
% Handle to figure object known
lg = findobj(figureobj, 'Type', 'legend');
% Handle to figure object unknown
lh = findobj(gcf, 'Type', 'legend');
请注意,gcf
通常会将句柄返回到用户单击的最后一个图形,但不一定总是如此。
自我宣传编辑:此方法包含在 *** MATLAB 社区的一组legend manipulation tools maintained on GitHub 中。
【讨论】:
是否有特殊原因避免再次调用legend
而使用undocumented 函数?
@SembeiNorimaki 因为它维护了lineseries 和图例条目之间的链接。
这太棒了!但是我无法让它在 R2017a 或 b 中工作。以新的顺序分配子代不会做任何事情(在使用 'set' 方法时也是如此)。它在 R2016b 中仍然可以正常工作。有什么想法吗?
嗨@Emil,很遗憾,R2017a 中引入的图形引擎改进broke most of this functionality。使用未记录功能的危险之一;不幸的是,我还没有时间研究替代方法。【参考方案2】:
对于使用早于 R2014b 的 MATLAB 版本的用户,另一种选择是通过将输出指定到 plot
来检索绘图对象的句柄。然后,您可以在将句柄传递给legend
之前按照您想要的顺序重新排列句柄。
x = 1:10;
y1 = x;
y2 = 2*x;
y3 = 3*x;
y4 = x.^2;
hplots = plot(x, y1, x, y2, x, y3, x, y4);
labels = 'y = x', 'y = 2*x', 'y = 3*x', 'y = x.^2';
% Indices specifying the order in which you want the legend entries to appear
neworder = [3 1 4 2];
legend(hplots(neworder), labels(neworder));
更新
为了在从文件加载时正确处理,您可以获取坐标轴的所有Children
以获取绘图对象并获取当前图例以获取标签。然后,您可以按照上述方法对它们重新排序。
load('filename.fig');
labels = get(legend(), 'String');
plots = flipud(get(gca, 'children'));
% Now re-create the legend
neworder = [3 1 4 2];
legend(plots(neworder), labels(neworder))
【讨论】:
【参考方案3】:我找到了一个 Matlab R2020 解决方案,可用于对图例条目重新排序,而不会弄乱它们相互叠加的顺序。我是从https://matplotlib.org/1.3.1/users/legend_guide.html找到的,很简单,只需要调用
legend([p2, p1], ["line 2", "line 1"])
其中 p1 是绘制时创建的线对象 p1 = 情节(...) 与 uistack 一起,我可以更改在其上绘制哪些对象,然后重新排序图例以使其有意义。示例
uistack(psave_d,'top') % Brings certain line to front
legend([psave_a, psave_b, psave_g, psave_c, psave_d, psave_e, psave_f, psave_pde], ["k_y=0.000001 W/m/K","k_y=0.0001 W/m/K","k_y=0.001 W/m/K","k_y=0.01 W/m/K","k_y=0.1 W/m/K","k_y=1 W/m/K","k_y=10 W/m/K","Isothermal PDE Numerical Model"])
如果有人需要更多细节,我很乐意提供。干杯
【讨论】:
【参考方案4】:根据我的经验和 excaza 其他地方的 cmets 回答,他们使用未记录函数的解决方案似乎在 R2017a 之后不再适用。
以下使用与 excaza 的原始答案相同的示例图,但不需要未记录的功能,并且似乎可以使用(至少)R2021a。它利用指定图形对象的subset 的能力来添加图例标签。此功能似乎保留了您传入这些图形对象的顺序。
例如,
x = 1:10;
y1 = x;
y2 = 2*x;
y3 = 3*x;
y4 = x.^2;
plot(x, y1, x, y2, x, y3, x, y4);
labels = 'y = x', 'y = 2*x', 'y = 3*x', 'y = x.^2';
legend(labels)
生产,
检索图形句柄允许以不同的顺序重新创建图例,
neworder = [3, 1, 4, 2];
ax = gca;
children = ax.Children;
legend(children(neworder), labels(neworder))
修改了之前的情节制作,
请注意,与another answer to a similar question 不同,这不需要在绘制图形句柄时显式返回并跟踪它们。使用 ax.Children
从轴中检索句柄。
【讨论】:
【参考方案5】:在 2021b 中,您可以重新排序 Legend
对象的未记录的 PlotChildren
属性,但您必须先将 AutoUpdate
属性设置为 'off'
:
hLegend = legend('Group A', 'Group C', 'Group B');
hLegend.AutoUpdate = 'off';
hLegend.PlotChildren = hLegend.PlotChildren([1,3,2]);
这不会影响绘图中图形对象的堆叠顺序。请注意:当AutoUpdate
设置为'off'
时,在向坐标区添加新图形对象时将不再自动添加或删除图例项。
【讨论】:
以上是关于Matlab:更改图例中条目的顺序的主要内容,如果未能解决你的问题,请参考以下文章