Skip to content

MATLAB - 对数坐标轴绘图

对数绘图对于可视化跨越多个数量级或遵循幂律或指数趋势的数据至关重要。与具有均匀间距的线性尺度不同,对数尺度会压缩大值范围,使趋势更加明显。MATLAB 提供了专用函数,用于创建在单轴或双轴上具有对数刻度的绘图。

在以下情况下,您应该考虑使用对数刻度:

  • 数据范围很广:例如,绘制信号的功率谱,其中值可以从非常小到非常大。
  • 突出指数趋势:指数增长或衰减 (y = A*e^(kx)) 在半对数图(线性 x,对数 y)上显示为直线。
  • 突出幂律趋势:幂律关系 (y = A*x^k) 在对数-对数图上显示为直线。

loglog() 函数创建一个 x 轴和 y 轴都使用以 10 为底的对数刻度的绘图。这对于可视化幂律关系是理想的。

% 生成遵循幂律的数据: y = 5 * x^1.5
x = logspace(-1, 2, 100); % 从 10^-1 到 10^2 的 100 个点
y = 5 * x.^1.5;
% 创建对数-对数绘图
figure; % 创建一个新的图形窗口
loglog(x, y, 'm-s', 'LineWidth', 1.5, 'MarkerFaceColor', 'y');
% 添加标签和标题以提高清晰度
title('Power-Law Relationship on a Log-Log Plot');
xlabel('X-axis (log scale)');
ylabel('Y-axis (log scale)');
grid on; % 添加网格以提高可读性

预期输出说明: 此代码生成一个双轴都是对数刻度的绘图。由于数据遵循幂律,因此生成的绘图是一条直线。此线的斜率对应于指数(1.5)。该线为洋红色,带有方形标记,填充色为黄色。

半对数图在一个轴上使用对数刻度,在另一个轴上使用线性刻度。

semilogy() 函数非常适合可视化指数数据,其中 y 轴是对数刻度,x 轴是线性刻度。

% 生成遵循指数增长的数据: y = exp(0.5x)
x = linspace(0, 10, 100);
y = exp(0.5 * x);
% 创建半对数绘图
figure;
semilogy(x, y, 'b--o', 'LineWidth', 1);
title('Exponential Growth on a Semi-Log Plot');
xlabel('X-axis (linear scale)');
ylabel('Y-axis (log scale)');
grid on;

预期输出说明: 此代码生成一个 y 轴为对数刻度的绘图。指数数据现在显示为一条直线。该绘图显示一条带有圆形标记的蓝色虚线。

semilogx() 函数用于 x 变量跨越多个数量级的情况。一个常见的应用是频率响应图(波特图)。

% 示例:简单 RC 滤波器的频率响应
f = logspace(1, 6, 200); % 频率从 10 Hz 到 1 MHz
R = 1000; % 1k 欧姆
C = 1e-6; % 1 微法
% 计算幅度
mag = 1 ./ sqrt(1 + (2*pi*f*R*C).^2);
% 创建半对数绘图
figure;
semilogx(f, mag, 'r-', 'LineWidth', 2);
title('Frequency Response of an RC Low-Pass Filter');
xlabel('Frequency (Hz) (log scale)');
drop('Magnitude (linear scale)');
grid on;

预期输出说明: 此代码生成滤波器的幅度响应图。x 轴(频率)是对数刻度,这是波特图的标准做法。该绘图显示了一条特征曲线,在低频时平坦,然后在高频时逐渐下降。

在现代 MATLAB 中,最佳实践是获取绘图对象的句柄以修改其属性。这提供了更多的控制,并使代码更简洁。

x = logspace(-1, 2, 50);
y1 = 10 * x.^2;
y2 = 1000 ./ x;
figure;
% 获取每条绘图线的句柄
p1 = loglog(x, y1);
hold on; % 保持当前绘图,以便添加另一条线
p2 = loglog(x, y2);
hold off;
% --- 使用句柄进行定制 ---
p1.LineStyle = '--';
p1.Color = 'blue';
p1.LineWidth = 2;
p2.Marker = 'd';
p2.MarkerEdgeColor = 'black';
p2.Color = 'red';
grid on;
title('Comparing Two Datasets');
xlabel('Input');
ylabel('Output');
legend('y = 10x^2', 'y = 1000/x', 'Location', 'southwest');

与在绘图函数内部将所有属性作为名称-值对传递相比,这种方法更具可读性和可扩展性。