Matlab:更改图例条目的顺序

3

我有一个Figure文件,希望可以改变条目的顺序(比如将第一个条目放在第三个)。我很久以前保存了这个Figure.fig文件,所以不确定是否可以恢复原始代码。

这里是我的绘图:

我的绘图

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

我可以直接从Matlab中的属性编辑器中更改图例中的条目顺序吗?如果可以,如何操作(我没有看到任何“顺序”属性或类似的内容)?否则,还有其他简单的方法来交换图例中的条目顺序吗?


如果您加载了图形,难道不能使用新的条目顺序再次执行“legend”吗? - user2261062
MATLAB的哪个版本? - sco1
这是Matlab R2015b。 - Patapunfate
这个图也是在R2015b中生成的吗? - sco1
是的,我非常肯定那就是。 - Patapunfate
5个回答

8
如果您的图形是在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');

产生:

start

然后您可以进行操作:

neworder = [3, 1, 4, 2];
lh.PlotChildren = lh.PlotChildren(neworder);

生产:

yay

如果您没有指向 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一般返回用户单击的最后一个图形的句柄,但这并不总是这样。
< p > < em > 自我推广编辑 :这种方法包含在一组由StackOverflow MATLAB社区维护的传奇操作工具中。

有什么特别的原因要避免再次调用 legend,而使用一个未记录的函数吗? - user2261062
1
@SembeiNorimaki 因为它保持了线系列和图例条目之间的链接。 - sco1
这很棒!但是我在R2017ab中无法让它工作。按照新顺序分配子项似乎没有任何作用(即使使用“set”方法)。在R2016b中仍然可以正常工作。有什么想法吗? - Emil
1
嗨@Emil,不幸的是,在R2017a引入的图形引擎改进中破坏了大部分此功能。使用未记录的功能的风险之一; 不幸的是,我还没有时间调查替代方法。 - sco1

8

如果使用比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
在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' 时,添加到坐标轴的新图形对象将不再自动添加或删除相应的图例项。

非常感谢您提供了这个使这个技巧起作用的一小部分信息。很高兴看到 Stack Overflow 中仍然有一小部分人对 Matlab 感兴趣 :) - z8080

0

根据我的经验和其他人在excaza的回答中的评论,看起来他们使用未记录的函数的解决方案可能在R2017a之后不再有效。

以下示例使用与excaza原始答案相同的示例图,但不需要未记录的功能,并且似乎在(至少)R2021a中有效。它利用了指定要向其添加图例标签的图形对象子集的能力。此功能似乎保留了您传递这些图形对象的顺序。

例如,

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))

修改之前的图形生成。

Plot with amended legend order

请注意,与类似问题的另一个答案不同的是,这不需要显式返回图形句柄并跟踪它们。这些句柄只需使用ax.Children从轴中检索即可。

0
我找到了一个 Matlab R2020 的解决方案,可以用来重新排列图例条目的顺序,而不会破坏它们叠加的顺序。我从 https://matplotlib.org/1.3.1/users/legend_guide.html 找到了它,它非常简单,你只需要调用函数即可。
legend([p2, p1], ["line 2", "line 1"])

当您绘制时创建行对象的p1 = plot(...),结合使用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"])

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接