情节外的图例不适用于 Octave 中的 plotyy
Legend outside plot does not work with plotyy in Octave
我正在尝试使用 plotyy
在 Octave 中创建一个图(在 Windows 上使用 v4.4.1)并将图例放在图外(因为数据涵盖了所有可用的 space 在图中)。以下 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 轴不可见(看起来图的一部分实际上被截断了)。
我曾尝试使用 qt
和 fltk
图形工具包,它们各自存在问题:
- 使用
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 似乎绘制了两个图例由于某种原因彼此重叠:一个具有第一组数据附加到第一组轴,一个具有完整数据集,两个轴都位于第一个图例的顶部。这显然是错误的,并且尝试将 hl
的 Visible
属性 设置为 off
会删除两个图例,而不仅仅是一个。
已更新:处理影响图形的图例放置和 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', []);
输出:
我正在尝试使用 plotyy
在 Octave 中创建一个图(在 Windows 上使用 v4.4.1)并将图例放在图外(因为数据涵盖了所有可用的 space 在图中)。以下 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 轴不可见(看起来图的一部分实际上被截断了)。
我曾尝试使用 qt
和 fltk
图形工具包,它们各自存在问题:
- 使用
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 似乎绘制了两个图例由于某种原因彼此重叠:一个具有第一组数据附加到第一组轴,一个具有完整数据集,两个轴都位于第一个图例的顶部。这显然是错误的,并且尝试将 hl
的 Visible
属性 设置为 off
会删除两个图例,而不仅仅是一个。
已更新:处理影响图形的图例放置和 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', []);
输出: