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 和图例条目之间的链接。 这太棒了!但是我无法让它在 R2017ab 中工作。以新的顺序分配子代不会做任何事情(在使用 '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:更改图例中条目的顺序的主要内容,如果未能解决你的问题,请参考以下文章

MATLAB:添加图标题轴标签图例更改字体大小

反转图例顺序而不更改绘图快速条形图中的条形顺序

在 Pandas 中更改图例的顺序

ggplot图例:更改自动图例的顺序

matlab中如何调整legend的位置?

matlab 2016a simulink 图例