MATLAB学习文档(二十八)

目录

11.4对匿名函数绘制二维线图(fplot)

[11.5创建具有两个 y 轴的图(yyaxis)](#11.5创建具有两个 y 轴的图(yyaxis))

11.6对数坐标图(semilogx、semilogy和loglog)


11.4对匿名函数绘制二维线图(fplot)

|-----------------|--------------------------------|---------------------------|---------------------------------|
| 功能 | 语法 | 返回对象 | 示例 |
| 绘制 f(x) | fplot(f, [xmin, xmax]) | FunctionLine | fplot(@(x)x.^2, [-1, 1]) |
| 绘制参数方程 | fplot(xt, yt, [tmin, tmax]) | ParameterizedFunctionLine | fplot(@cos, @sin, [0, 2*pi]) |
| 自定义样式 | fplot(..., 'Name', Value, ...) | 同上 | fplot(@sin, 'LineWidth', 2) |

11.4.1. 核心概念:fplot 与 plot 的区别

  • plot:需要你先计算出一系列离散的数据点 (x, y),然后用线连接这些点。plot(x, y) 绘制的是你给定的数据。
  • fplot:你只需提供一个函数句柄,fplot 会自动地在指定区间内进行智能采样,并绘制出一条平滑的函数曲线。fplot(f) 绘制的是函数本身。

fplot 的优势在于它能自适应地选择采样点,在函数变化剧烈的地方增加采样密度,在平缓的地方减少采样,从而用更少的点画出更精确的曲线。

11.4.2. 绘制单个匿名函数 f(x)

这是 fplot 最核心的用法,直接传入一个关于 x 的函数句柄。

语法:
Matlab 复制代码
fplot(f)

fplot(f, [xmin, xmax])

h = fplot(...) % 返回图形对象句柄
参数说明:
  • f:函数句柄,通常是一个匿名函数,如 @(x) sin(x) ./ x。
  • xmin, xmax\]:可选,指定 x 的绘图区间。默认为 \[-5, 5\]。

Matlab 复制代码
% 定义一个匿名函数

myFunc = @(x) sin(x) .* exp(-x/5);

% 在默认区间 [-5, 5] 绘制

figure;

fplot(myFunc);

title('在默认区间绘制');

% 在指定区间 [0, 10] 绘制

figure;

fplot(myFunc, [0, 10]);

title('在指定区间 [0, 10] 绘制');

grid on;

11.4.3在使用 fplot 时,最常遇到的警告是:

Warning:

Function behaves unexpectedly on array inputs. To improve performance, properly vectorize your function to return an array with the same size as the input.

原因分析:

fplot 为了提高效率,会尝试向量化你的函数,即一次性传入一个向量 x,并期望得到一个同样大小的向量 y。如果你的函数中使用了无法处理向量的运算符(如 ^ 而不是 .^),就会触发此警告。

示例与解决:
Matlab 复制代码
% 错误的写法(会触发警告)

badFunc = @(x) x^2; % 使用了矩阵幂 ^

fplot(badFunc, [-2, 2]); % MATLAB会发出警告并尝试修复

% 正确的写法(向量化)

goodFunc = @(x) x.^2; % 使用了数组幂 .^

fplot(goodFunc, [-2, 2]); % 运行流畅,无警告
核心原则:

在为 fplot 创建匿名函数时,始终使用数组运算符(.*, ./, .^)。

11.4.4绘制参数方程 x(t) 和 y(t)

fplot 也可以轻松绘制由参数方程定义的曲线,如圆、螺旋线等。

语法:
Matlab 复制代码
fplot(xt, yt)

fplot(xt, yt, [tmin, tmax])

h = fplot(...)
参数说明:
  • xt:关于参数 t 的 x 坐标函数句柄。
  • yt:关于参数 t 的 y 坐标函数句柄。
  • tmin, tmax\]:可选,指定参数 t 的范围。默认为 \[-5, 5\]。

Matlab 复制代码
% 定义一个圆的参数方程

xt = @(t) cos(t);

yt = @(t) sin(t);

% 绘制一个完整的圆 (t 从 0 到 2*pi)

figure;

fplot(xt, yt, [0, 2*pi]);

title('单位圆');

axis equal; % 保证x,y轴比例相同,使圆不被拉伸成椭圆

grid on;

11.4.5 fplot 常用的名称-值参数

与 plot 类似,fplot 也支持通过名称-值参数对来定制线条样式、颜色等。

|-----------------|------------|------------------------------|
| 参数名 | 描述 | 示例值 |
| LineColor | 线条颜色 | 'r', 'blue', [0, 0.5, 0.8] |
| LineStyle | 线条样式 | '--', ':', '-.' |
| LineWidth | 线条宽度 | 1.5, 2 |
| Marker | 数据点标记 | 'o', '+', '*' |
| MarkerSize | 标记大小 | 8, 10 |
| MeshDensity | 网格密度(采样点数) | 50 (默认), 100, 200 |

使用举例:
Matlab 复制代码
f = @(x) tanh(x);

fplot(f, [-3, 3], 'LineWidth', 2, 'Color', [0.2 0.6 0.8], 'LineStyle', '-.');

title('自定义样式的双曲正切函数');

grid on;

11.4.6 fplot 返回的图形对象

这是 fplot 与 plot 的一个关键区别。

  • fplot 返回的不是简单的 Line 对象,而是更专门的函数对象。
  • fplot(f(x)) 返回 FunctionLine 对象。
  • fplot(x(t), y(t)) 返回 ParameterizedFunctionLine 对象。

这些对象是 Line 对象的子类,它们不仅包含了线条的所有视觉属性,还额外保存了用于绘制的函数句柄。

这意味着你可以在绘图后,直接修改其底层的函数定义,图形会自动更新!

示例:

Matlab 复制代码
% 绘制 sin(x)

h_func = fplot(@sin, [-2*pi, 2*pi]);

title('原始函数: sin(x)');

pause(2);

% 修改句柄中的函数,无需重新绘制!

h_func.Function = @(x) cos(x);

title('修改后函数: cos(x)');

11.4.7. 知识扩展

与 fplot 类似的函数:ezplot(不推荐)

在旧版本的MATLAB中,ezplot (Easy Plot) 也用于绘制函数。fplot 是 ezplot 的现代化和功能增强版。

为什么不推荐 ezplot?

  • 性能与精度:fplot 的自适应采样算法更先进,绘图更快、更精确。
  • 返回对象:fplot 返回可操作的 FunctionLine 对象,而 ezplot 的返回值在不同版本中行为不一致,功能有限。
  • 一致性:fplot 的语法和名称-值参数对与MATLAB其他现代绘图函数(如 plot)更加一致。

结论:

在所有新项目中,都应优先使用 fplot。

绘制多函数

可以在同一个 fplot 调用中绘制多个函数,或者使用 hold on。

方法一:使用 hold on
Matlab 复制代码
figure;

fplot(@sin, [-2*pi, 2*pi]);

hold on;

fplot(@(x) cos(x), 'r--');

legend('sin(x)', 'cos(x)');
方法二:传入句柄数组
Matlab 复制代码
figure;

fplot([@sin, @cos], [-2*pi, 2*pi]);

legend({'sin(x)', 'cos(x)'});
fimplicit 绘制隐函数

对于形如 f(x, y) = 0 的隐函数(如 x^2 + y^2 - 1 = 0),应使用 fimplicit 函数,它是 fplot 在隐函数领域的姊妹函数。

Matlab 复制代码
fimplicit(@(x,y) x.^2 + y.^2 - 1);

axis equal;

title('单位圆 (隐函数)');

11.5创建具有两个 y 轴的图(yyaxis)

|----------------------------|----------------------|---------------------------------------------|
| 命令 | 功能 | 作用范围 |
| yyaxis left | 激活左侧 Y | 之后的所有绘图、ylabel、set(gca, 'YColor')等命令都只作用于左侧 |
| yyaxis right | 激活右侧 Y | 之后的所有绘图、ylabel、set(gca, 'YColor')等命令都只作用于右侧 |
| xlabel / title | 设置X轴标签/标题 | 全局 ,无论当前激活哪个Y轴,都会作用于整个坐标区 |

11.5.1. 核心概念:为什么需要双Y轴?

在单Y轴图表中,所有数据共享同一个Y轴刻度。当你想在同一张图上绘制两组数据,例如:

  • 温度(范围:20-30°C)和降雨量(范围:0-200mm)
  • 股票价格(范围:100-150元)和成交量(范围:100万-500万股)

如果强行使用同一个Y轴,其中一组数据的波动趋势会因为刻度问题而变得几乎不可见。

双Y轴图表通过为左右两侧Y轴设置独立的刻度和标签,完美地解决了这个问题,使得两组数据都能清晰地呈现。

11.5.2. yyaxis 的核心语法与工作模式

yyaxis 的核心思想是"激活"一个Y轴侧,之后所有的绘图和标签设置命令都只会作用于这一侧。

语法
Matlab 复制代码
yyaxis left   % 激活左侧Y轴

yyaxis right  % 激活右侧Y轴
工作流程
  1. 使用 yyaxis left 激活左侧Y轴。
  2. 绘制与左侧Y轴关联的数据(使用 plot, bar, stairs 等)。
  3. 设置左侧Y轴的标签(ylabel)。
  4. 使用 yyaxis right 激活右侧Y轴。
  5. 绘制与右侧Y轴关联的数据。
  6. 设置右侧Y轴的标签。
  7. 最后,设置共用的X轴标签和标题。

11.5.3. 不同使用方法的举例

11.5.3.1 基础示例:绘制温度与降雨量

这是最典型的应用场景,展示了如何将两组不同单位的数据绘制在一起。

Matlab 复制代码
% 1. 准备数据

months = 1:12;

temperature = [5, 7, 12, 18, 22, 28, 31, 30, 25, 19, 12, 6]; % 温度 (°C)

rainfall = [80, 70, 90, 120, 150, 180, 200, 190, 140, 100, 80, 75]; % 降雨量 (mm)

% 2. 创建图表并激活左侧Y轴

figure;

yyaxis left;

% 3. 绘制温度数据并设置左侧Y轴

plot(months, temperature, 'o-', 'Color', 'r', 'LineWidth', 2);

ylabel('温度 (°C)', 'Color', 'r'); % 标签颜色与线条对应

set(gca, 'YColor', 'r'); % Y轴刻度颜色也与线条对应

% 4. 激活右侧Y轴

yyaxis right;

% 5. 绘制降雨量数据并设置右侧Y轴

bar(months, rainfall, 'FaceColor', 'b', 'Alpha', 0.5);

ylabel('降雨量 (mm)', 'Color', 'b');

set(gca, 'YColor', 'b');

% 6. 设置共用元素

xlabel('月份');

title('年度温度与降雨量关系');

grid on;

xticks(months);
11.5.3.2 高级示例:在同一侧绘制多条线

你可以很方便地在同一侧Y轴上绘制多条数据,它们将共享该侧的刻度。

Matlab 复制代码
% 准备数据

x = linspace(0, 10);

y1 = sin(x);

y2 = cos(x);

y3 = exp(x/5);

figure;

% 左侧Y轴:绘制三角函数

yyaxis left;

plot(x, y1, 'b-');

hold on;

plot(x, y2, 'r--');

ylabel('三角函数值');

legend('sin(x)', 'cos(x)', 'Location', 'northwest');

% 右侧Y轴:绘制指数函数

yyaxis right;

plot(x, y3, 'g:', 'LineWidth', 2);

ylabel('指数函数值');

% 设置共用元素

xlabel('X轴');

title('多函数对比');

grid on;

11.5.4. 知识扩展

11.5.4.1 yyaxis 与旧版 plotyy 的区别

在R2016a版本之前,MATLAB使用 plotyy 函数来创建双Y轴图。现在,强烈推荐使用 yyaxis,原因如下:

|----------|--------------------------------|---------------------------------------------|
| 特性 | yyaxis ( 推荐 ) | plotyy ( 旧版 , 不推荐 ) |
| 语法 | 命令式 ,逻辑清晰,易于扩展 | 函数式 ,参数复杂,难以添加多条线 |
| 句柄控制 | 返回单个坐标区句柄,通过 yyaxis 切换 | 返回两个坐标区句柄,操作繁琐 |
| 兼容性 | 与现代绘图函数(如 hold on, legend)完美兼容 | 常与 hold on 等产生意外行为 |
| 灵活性 | 可以轻松地在任意一侧添加任意数量的图形 | 添加额外图形非常困难 |

结论:除非你在维护必须使用旧版MATLAB的代码,否则应始终使用 yyaxis。

11.5.4.2 获取两侧Y轴的属性

虽然 yyaxis 简化了操作,但有时你仍需直接获取或设置某一侧Y轴的属性。你可以通过坐标区的 YAxis 属性来访问。

Matlab 复制代码
% 继续上面的例子

ax = gca; % 获取当前坐标区句柄

% 获取左侧Y轴的刻度范围

left_lim = ax.YAxis(1).Limits;

% 获取右侧Y轴的标签

right_label = ax.YAxis(2).Label.String;

% 修改右侧Y轴的刻度格式为科学计数法

ax.YAxis(2).TickLabelFormat = '%.1e';

这里,YAxis 是一个包含两个 ruler 对象的数组,YAxis(1) 对应左侧,YAxis(2) 对应右侧。

11.5.4.3 图例的智能处理

如示例11.5.3.2所示,当你在不同侧绘制了多条线后,调用 legend 会自动将所有线条的图例整合在一起,非常方便。你只需要在所有绘图完成后,调用一次 legend 即可。

11.6对数坐标图(semilogx、semilogy和loglog)

|--------------|---------------|---------------|--------------|----------------|
| 函数 | X 轴刻度 | Y 轴刻度 | 典型应用场景 | 示例 |
| semilogx | 对数 | 线性 | 频率响应、频谱分析 | semilogx(f, H) |
| semilogy | 线性 | 对数 | 指数增长/衰减、误差分析 | semilogy(t, N) |
| loglog | 对数 | 对数 | 幂律关系、分形几何 | loglog(x, y) |

11.6.1. 核心概念:为什么使用对数坐标?

在标准的线性坐标图中,坐标轴的刻度是均匀的(例如,1, 2, 3, 4...)。

但当数据的跨度非常大时(例如,从0.01到1000000),线性坐标图会产生严重问题:

  • 小数值被"压扁":数值较小的数据变化会变得无法分辨。
  • 大数值占据大部分空间:图表的大部分区域被大数值占据,无法看清细节。

对数坐标图通过将坐标轴的刻度转换为对数尺度(例如,0.01, 0.1, 1, 10, 100...)来解决此问题。

这使得:

  • 关注数量级变化:能清晰地展示数据在不同数量级上的相对变化。
  • 识别指数关系:在对数坐标下,指数关系 y = a * b^x 会呈现为一条直线。
  • 展示宽动态范围数据:如频率响应、地震震级、信号频谱等。

11.6.2. 三种对数坐标函数

MATLAB提供了三个专门的函数来创建不同类型的对数坐标图。

  • semilogx:X轴为对数刻度,Y轴为线性刻度。
  • semilogy:Y轴为对数刻度,X轴为线性刻度。
  • loglog:X轴和Y轴均为对数刻度。

它们的语法与 plot 函数几乎完全相同。

语法:

Matlab 复制代码
semilogx(X, Y)

semilogy(X, Y)

loglog(X, Y)

semilogx(Y) % 当X是1:length(Y)时

semilogx(X, Y, LineSpec)

semilogx(X, Y, Name, Value, ...)

h = semilogx(...) % 返回图形对象句柄

参数说明:

  • X, Y:数据向量或矩阵,用法与 plot 完全一致。
  • LineSpec:线条规格符(如 'r-o')。
  • Name, Value:名称-值参数对(如 'LineWidth', 2)。

11.6.3. 不同使用方法的举例

11.6.3.1 semilogx:X轴对数坐标

常用于分析频率响应、滤波器特性等。

示例:绘制一个一阶低通滤波器的幅频响应曲线。

Matlab 复制代码
% 准备数据:频率

f = logspace(0, 5, 200); % 从10^0到10^5生成200个对数间隔的点

fc = 1000; % 截止频率

% 计算幅频响应

H = 1 ./ sqrt(1 + (f / fc).^2);

% 使用 semilogx 绘图

figure;

semilogx(f, H);

title('一阶低通滤波器幅频响应');

xlabel('频率 (Hz) - 对数坐标');

ylabel('幅值 |H(f)| - 线性坐标');

grid on;

% 添加标记以突出截止频率

hold on;

semilogx([fc, fc], [0, 1/sqrt(2)], 'r--');

text(fc*1.5, 1/sqrt(2), '截止频率');
11.6.3.2 semilogy:Y轴对数坐标

常用于显示指数增长/衰减过程,如人口增长、放射性衰变、细菌繁殖等。

示例:模拟细菌指数增长。

Matlab 复制代码
% 准备数据:时间

t = 0:10;

N0 = 100; % 初始细菌数量

r = 0.5;  % 增长率

% 计算细菌数量

N = N0 * exp(r * t);

% 使用 semilogy 绘图

figure;

semilogy(t, N, 'o-', 'LineWidth', 2, 'MarkerFaceColor', 'b');

title('细菌指数增长');

xlabel('时间 (小时)');

ylabel('细菌数量 - 对数坐标');

grid on;

% 注意:指数函数在对数Y轴下呈现为一条直线
11.6.3.3 loglog:双对数坐标

常用于分析幂律关系,如分形、网络科学、物理学中的各种标度律。

示例:绘制幂律函数 y = 5 * x^(-2)。

Matlab 复制代码
% 准备数据

x = logspace(-2, 2, 100);

y = 5 * x.^(-2);

% 使用 loglog 绘图

figure;

loglog(x, y, 'r-', 'LineWidth', 2);

title('幂律关系 y = 5 * x^{-2}');

xlabel('X - 对数坐标');

ylabel('Y - 对数坐标');

grid on;

% 注意:幂律函数在双对数坐标下呈现为一条直线

11.6.4. 知识扩展

11.6.4.1 使用 plot + set 方法

你也可以先用 plot 绘图,然后通过设置坐标轴的 XScale 和 YScale 属性来转换为对数坐标。这提供了更大的灵活性。

Matlab 复制代码
% 先用线性坐标绘图

plot(x, y);

% 然后设置坐标轴属性

set(gca, 'XScale', 'log'); % X轴变为对数

set(gca, 'YScale', 'log'); % Y轴变为对数

% 或者 set(gca, 'YScale', 'linear'); 变回线性

这种方法的好处是,你可以在一个脚本中动态地切换坐标轴类型,而无需重写绘图函数。

11.6.4.2 负值与零值问题

对数函数在数学上对非正数(零和负数)是无定义的。因此,当你尝试绘制包含零或负值的数据时,MATLAB会:

忽略这些点:这些数据点不会在图上显示。

给出警告:命令行窗口会提示 "Negative data ignored" 或类似信息。

解决方案:

  • 检查数据:确保你的数据在预期的对数范围内。
  • 数据偏移:如果数据是相对于某个基准值的偏差(例如,误差),可以考虑加上一个小的常数 c 使得所有数据都为正:semilogy(x, y + c)。
  • 使用 symlog (Symbolic Log) 刻度:在某些领域(如信号处理),需要一种能同时显示正负值的对数刻度。MATLAB原生没有直接的 symlog 函数,但可以在 File Exchange 上找到用户贡献的实现。
11.6.4.3 坐标轴刻度标签格式

在对数坐标中,刻度是10的幂次。你可以自定义这些标签的显示格式。

Matlab 复制代码
loglog(x, y);

h_ax = gca;

% 将刻度标签从 10^2, 10^3... 改为 100, 1000...

h_ax.YAxis.TickLabelFormat = '%.0f';
相关推荐
爱敲代码的loopy1 小时前
MATLAB函数全称解析:旋转翻转找数字
开发语言·matlab
Freedom_my1 小时前
插入排序算法
数据结构·算法·排序算法
952361 小时前
排序-算法
数据结构·算法·排序算法
WongKyunban1 小时前
插入排序的原理和示例
数据结构·算法·排序算法
flashlight_hi2 小时前
LeetCode 分类刷题:404. 左叶子之和
javascript·算法·leetcode
chao1898442 小时前
基于BP神经网络的故障分类MATLAB实现
神经网络·matlab·分类
月屯2 小时前
后端go完成文档分享链接功能
开发语言·后端·golang
('-')2 小时前
《从根上理解MySQL是怎样运行的》第四章学习笔记
笔记·学习·mysql
Franciz小测测2 小时前
Python连接RabbitMQ三大方案全解析
开发语言·后端·ruby