Matlab:更改图例中条目的顺序

Matlab: change order of entries in Figure legend

我有一个图形文件,我想在其中更改条目的顺序(例如,将第一个条目放在第三个条目中)。我很久以前就保存了这个 Figure.fig 所以我不确定我是否可以恢复原始代码。

这里我给大家展示一下我的剧情:

我希望图例元素按降序排列(如图所示),但由于错误,我的第二个条目指的是错误的情节(它说“25 年”,但情节实际上是指最低趋势,对应“9年”趋势。

我可以直接从 Matlab 中图形的属性编辑器切换图例中条目的顺序吗?如果是,如何(我没有看到任何 "Order" 属性 或类似内容)?否则有没有其他简单的方法来切换图例中条目的顺序?

如果您的图形是在 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 object containing the axes object your data is plotted on. You can find the handle to your legend object using one of the following findobj 方法的子对象:

% Handle to figure object known
lg = findobj(figureobj, 'Type', 'legend');

% Handle to figure object unknown
lh = findobj(gcf, 'Type', 'legend');

请注意,gcf 通常 returns 用户单击的最后一个图形的句柄,但不一定总是如此。


自我推销编辑:该方法包含在 Whosebug MATLAB 社区的一组 legend manipulation tools maintained on GitHub 中。

对于那些使用早于 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))

我找到了一个 Matlab R2020 解决方案,可用于 re-order 图例条目,而不会弄乱它们在彼此之上绘制的顺序。我是从 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"])

如果有人需要更多细节,我很乐意提供。干杯

根据我的经验和其他地方对 excaza 回答的评论,他们使用未记录函数的解决方案似乎在 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.

从轴中简单地检索句柄

在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' 时,向坐标区添加新图形对象时将不再自动添加或删除图例项。