情节外的传说不适用于 Octave 中的 plotyy

Posted

技术标签:

【中文标题】情节外的传说不适用于 Octave 中的 plotyy【英文标题】:Legend outside plot does not work with plotyy in Octave 【发布时间】:2019-04-13 06:11:33 【问题描述】:

我正在尝试使用plotyy 在 Octave(在 Windows 上使用 v4.4.1)中创建一个图,并将图例放在图之外(因为数据涵盖了图中的所有可用空间)。以下 MVCE 应该可以很好地重现该问题:

% Generate some random data to reproduce the issue
data = rand(1000,10);
data(:,1:8) = data(:,1:8)-0.5;
data(:,9:10) = data(:,9:10)+30;
timedate = linspace(737310,737313,size(data,1));
data_labels='1';'2';'3';'4';'5';'6';'7';'8';'9';'10';

% Plot the data
figure('Name','MVCE','Position',[300 200 1000 600])
[ax,h1,h2] = plotyy(timedate,data(:,1:8),timedate,data(:,9:10));
set(h2,'Visible','on'); 
datetick(ax(1),'x','HH:MM:SS')
datetick(ax(2),'x','HH:MM:SS')
ylim(ax(1),[-1 1])
ylim(ax(2),[20 50])
xlabel('Date & time')
ylabel(ax(1),'Something')
ylabel(ax(2),'Something else')
title('plotyy graph with legend problem')
[hl,hlo] = legend([h1;h2],data_labels,'location','eastoutside');
grid on

这是使用gnuplot图形工具包的代码输出:

如您所见,图例没有超出情节,并且第二个 y 轴不可见(看起来情节的一部分实际上被截断了)。

我尝试过使用qtfltk 图形工具包,它们会给出自己的问题:

    带有qt图形工具包

    带有fltk图形工具包

任何人都可以建议修复或至少解决方法吗?同样的问题是否也发生在 MATLAB 中,还是 Octave 特有的?

编辑 使用 Tasos 回答中的建议,我几乎设法使它与 gnuplot 一起工作:

% Plot the data
figure('Name','MVCE','Position',[300 200 1000 600])
[ax,h1,h2] = plotyy(timedate,data(:,1:8),timedate,data(:,9:10));
set(h2,'Visible','on'); 
datetick(ax(1),'x','HH:MM:SS')
datetick(ax(2),'x','HH:MM:SS')
ylim(ax(1),[-1 1])
ylim(ax(2),[20 50])

ax1Pos = get(ax(1), 'position');   
ax2Pos = get(ax(2), 'position');
ax1Pos(3) = ax1Pos(3) * 0.73;      
ax2Pos(3) = ax2Pos(3) * 0.73;
set(ax(1), 'position', ax2Pos);    
set(ax(2), 'position', ax2Pos);

xlabel('Date & time')
ylabel(ax(1),'Something')
ylabel(ax(2),'Something else')
title('plotyy graph with legend problem')
[hl,hlo] = legend([h1;h2],data_labels,'location','eastoutside');
pos = get(hl,'Position');
pos(1) = 0.9;
set(hl,'Position',pos)
grid on

产生:

除了图例与第二个 y 轴标签重叠(它不在我的屏幕上,仅在打印到 jpg 时)这一事实之外,问题在于 Octave 似乎在每个图例的顶部绘制了两个图例其他出于某种原因:一个将第一组数据附加到第一组轴,一个具有完整数据集,两个轴都位于第一个图例的顶部。这显然是错误的,尝试将hlVisible 属性设置为off 会删除两个图例,而不仅仅是一个。

【问题讨论】:

我认为应该删除 MATLAB 标签,因为这个问题是 Octave 特有的。除了增加曝光率之外,还有其他原因吗? @Dev-iL 公平评论 - 我认为它也可能适用于 MATLAB,因为语法相同并且应该适用于两个平台。我不能说在 MATLAB 上是否也会出现同样的问题。虽然这可能是 Octave 特有的,但一些具有 MATLAB 知识的人可能会提出宝贵的建议来解决这个问题。如果您确实认为 MATLAB 选项卡不合适,请随时将其删除。 事实上,如果有人可以访问 MATLAB,我很想知道在 MATLAB 中是否会发生同样的事情。 无法在 MATLAB R2017b 中重现,图例出现在绘图之外,并显示第二个 y 轴,带有标签等(尽管第二个 y 轴标签被图例覆盖,但这可能又是一个不同的问题)。我已相应地删除了 MALTAB 标记,如果您有直接的理由将其链接到 MATLAB,请恢复它。也许标记图形工具包而不是 【参考方案1】:

更新:处理图例放置和影响图形的 OpenGL 精度。

对于图例没有出现在你想要的位置的问题,你可以手动调整一个图形中所有轴的位置,把它们放在你想要的位置。

关于 OpenGL 无法处理将小数添加到大数时所涉及的精度的问题,仅绘制涉及小数的图形,然后简单地调整 xticklabels 以对应您想要的数字。

完整代码如下:

% Generate some random data to reproduce the issue
data = rand(1000,10);
data(:,1:8) = data(:,1:8)-0.5;
data(:,9:10) = data(:,9:10)+30;
t_offset = 737310;
timedate = linspace(0,3,size(data,1));
data_labels='1';'2';'3';'4';'5';'6';'7';'8';'9';'10';

% Plot the data
figure('Name','MVCE','Position',[300 200 1000 600])
[ax,h1,h2] = plotyy(timedate,data(:,1:8),timedate,data(:,9:10));
set(h2,'Visible','on'); 
ylim(ax(1),[-1 1])
ylim(ax(2),[20 50])
ylabel(ax(1),'Something')
ylabel(ax(2),'Something else')
title('plotyy graph with legend problem')
[hl,hlo] = legend([h1;h2],data_labels,'location','eastoutside');
set(hl, 'position', get(hl, 'position') .* [0.975, 1, 0.975, 1] )
grid on

ax1Pos = get(ax(1), 'position');   ax2Pos = get(ax(2), 'position');
ax1Pos(3) = ax1Pos(3) * 0.95;      ax2Pos(3) = ax2Pos(3) * 0.95;
set(ax(1), 'position', ax2Pos);    set(ax(2), 'position', ax2Pos);
XTicks = get(ax(1), 'xtick');
set(ax(1), 'xticklabel', datestr(XTicks + t_offset, 'HH:MM:SS'))
xlabel('Date & time')
set(ax(2), 'xtick', []);

输出:

【讨论】:

谢谢。然而,数据看起来不对,全是乱七八糟的。只有 gnuplot 图形工具包似乎可以正确绘制数据。 @am304 我们是在谈论传说问题还是别的什么?你预计会发生什么? 您可以看到qtfltk 的数据看起来是错误的,丢失了大块数据。这是因为当 Octave 将数据传递到 OpenGL 后端时,它会自动从双精度转换为单精度(因为 OpenGL 是 32 位的)。 Octave 中日期的问题在于它们是相当大的数字,从一个数据点到下一个数据点的变化很小,在数据类型转换中会丢失。所以不幸的是,我不能使用qtfltk 图形工具包,因此。不过,您的建议确实让我更进一步。 谢谢,它成功了。我不得不调整轴和图例的缩放和偏移因子,就像“真实”数据一样,图例字符串有点长,而且当保存为 JPG 时,它看起来与屏幕上的不同,但基本上它有效. 只是一个随机的、可能无关的想法。我最终没有在这里使用它,但我经常最终依赖多个透明的“轴”层,它们位于同一个地方,x 轴/刻度适当地打开或关闭,只包含我需要的绘图元素。记住这是一个有用的技巧,并且通常比简单地尝试在同一个轴对象上绘制所有内容要好得多。在更糟糕的情况下,您甚至可以单独生成这些图层,并依赖一个简单的 gimp 脚本为您将图层与透明度结合起来。

以上是关于情节外的传说不适用于 Octave 中的 plotyy的主要内容,如果未能解决你的问题,请参考以下文章

在 Rmarkdown 中动态创建选项卡不适用于 ggplot,而它适用于 plotly

安全区域布局指南不适用于情节提要中的 UITableViewController

Plotly:如何更改图例中显示的线条的大小?

复制粘贴不适用于 spyder 中的绘图

如何在 Plotly 的图中定位图例

plotly:单击图例中的点时突出显示(暗淡),而不是过滤