如何在每行上添加标签并将第二个 y 轴添加到 'loglog' 图的右侧?

How to add labels on each line and add 2nd y-axes to the right side of the 'loglog' plot?

最近我正在尝试为道路评估实施 ISO 分类。请参考论文The use of vehicle acceleration measurements to estimate road roughness。但是我遇到了一些关于绘制 ISO 分类图的问题。代码如下:

%% generate ISO Clasification Curve (m^2/(rad/m))
AngSpaFre = 10^(-3):0.01:10^2;                                  % spatial frequency (rad/m)
ParamTable = [0              1*10^(-6)       2*(10^(-6));       % ISO classification parameters
              2*(10^(-6))    4*(10^(-6))     8*(10^(-6));       % (lower bound, geometric average, upper bound)
              8*(10^(-6))    16*(10^(-6))    32*(10^(-6));
              32*(10^(-6))   64*(10^(-6))    128*(10^(-6));
              128*(10^(-6))  256*(10^(-6))   512*(10^(-6));
              512*(10^(-6))  1024*(10^(-6))  2048*(10^(-6));
              2048*(10^(-6)) 4096*(10^(-6))  8192*(10^(-6));
              8192*(10^(-6)) 16384*(10^(-6)) 32768*(10^(-6))];
class_num = 8;
len = length(AngSpaFre);
iso_table = zeros(class_num, len);
for i = 1:class_num
  geo_mean = ParamTable(i, 2);
  geo_upbound = ParamTable(i, 3);
  for j = 1:len
    if(AngSpaFre(j) <= 1)
        iso_table(i,j) = geo_mean*(AngSpaFre(j)^(-2));
    else
        iso_table(i,j) = geo_mean*(AngSpaFre(j)^(-1.5));
    end
  end
end

figure,
ht = loglog(AngSpaFre, iso_table(1,:), AngSpaFre, iso_table(2,:), AngSpaFre, iso_table(3,:), AngSpaFre, iso_table(4,:), AngSpaFre, iso_table(5,:), AngSpaFre, iso_table(6,:), AngSpaFre, iso_table(7,:), AngSpaFre, iso_table(8,:));
hY = get(gca,'ylim');
hold on;
loglog([1 1], hY);
xlabel('Spatial Frequency \Omega (rad/m)');
ylabel('PSD (m^2/(rad/m))'); 
title('ISO Classification (log-log scale)');

当前结果如下图所示:

然后我的实现中出现了2个问题,希望有人能给我一些解决方案或简单的例子来说明问题。

Q1: 因为分类曲线应该识别道路的质量等级。所以我想在每行下面添加标签来指示级别,如下图所示。我怎样才能在matlab中实现这一点?

Q2: 另外,我想在 'loglog' 图的右侧添加另一个 y 轴,没有如图所示的对数刻度值以下。如何做到这一点?我参考了官方网站上的许多示例,但大多数都集中在 'plot'/'plotyy' 示例上。 :(

回答第一部分

在某处放置文本的常用方法是 annotation function. It's quite hard do get it right with its basic functions, so rather use it with the latex interpreter as it allows you to specify the gap between every line with '\vspace{gapwidth}' and a lot more options:

strings = {'H','G','F','E','D','C','B','A'};
verticalspace = '\vspace{4pt}';
str = cellfun(@(x) [x verticalspace],strings,'uni',0);


annotation('textbox', [0.4,0.6,0.1,0.1],...
           'String', str,...
           'LineStyle','none','Interpreter','latex');

这确实很麻烦,您应该使用固定的图形宽度。

另一种方法是使用 并根据需要调整它们。优点是文本框的位置是相对于你的数据而不是数字。

我的一般建议:根本不要使用 Matlab 进行此类调整,这很痛苦...。将图形保存为 pdf (set(gcf,'renderer','painters')) 并使用任何矢量图形程序或直接使用 LaTeX/Tikz.

进行 post 处理

回答第二部分

要获得第二个轴,请使用:

ax1 = gca;
ax2 = axes('Position',ax1.Position,'Color','none');
ax2.YAxisLocation = 'right';
ax2.YLim = [0, 120];
ax2.YTick = 0:10:120;
ax2.XTick = [];

再一次,请在之前指定确切的图形尺寸!事后调整大小只会带来麻烦。

总结

您当前代码下的所有内容:

%%
f = gcf;
f.Units = 'pixels';
f.Position = ([100,100,1000,800]);

%%
strings = {'H','G','F','E','D','C','B','A'};
verticalspace = '\vspace{7.6pt}';
str = cellfun(@(x) [x verticalspace],strings,'uni',0);

annotation('textbox', [0.4,0.61,0.1,0.1],...
           'String', str,...
           'LineStyle','none','Interpreter','latex');

%%
ax1 = gca;
ax2 = axes('Position',ax1.Position,'Color','none');
ax2.YAxisLocation = 'right';
ax2.YLim = [0, 120];
ax2.YTick = 0:10:120;
ax2.XTick = [];
linkaxes([ax1,ax2],'x')

会给出(未调整大小):