本页对应的英文页面已更新,但尚未翻译。 若要查看最新内容,请点击此处访问英文页面。

插入网格数据

网格数据表示

网格表示

此示例说明如何使用 meshgridndgrid 创建二维网格。

在 MATLAB® 中,网格数据表示网格中的有序数据。要理解有序数据,您可以思考 MATLAB 在矩阵中存储数据的方式。

定义一些数据。

A = gallery('uniformdata',[3 5],0)
A = 3×5

    0.9501    0.4860    0.4565    0.4447    0.9218
    0.2311    0.8913    0.0185    0.6154    0.7382
    0.6068    0.7621    0.8214    0.7919    0.1763

MATLAB 在矩阵中存储数据。可以将 A 视为一组按矩阵索引排序的元素位置。A 的线性索引为:

[147101325811143691215]

可通过索引来检索矩阵中的任何元素,即请求矩阵中该位置上的元素。通过 A(i) 可检索 A 中的第 i 个元素。

检索 A 中的第 7 个元素。

A(7)
ans = 0.4565

对于 m×n 矩阵,可通过将 i 偏移 1 位来求与第 i 个元素相邻的列元素。若要求与第 i 个元素相邻的行元素,需将 i 偏移 m 位。

i-1i-mii+mi+1

检索与 A(7) 相邻的列元素。

A(6),A(8)
ans = 0.7621
ans = 0.0185

MATLAB 使用类似的思路创建数据网格。网格不只是一个符合特定几何属性的点集,更是一个依赖于网格中的点之间的有序关系的网格数据集。网格结构体中随时可用的相邻信息对于许多应用(尤其是基于网格的插值)非常有用。

MATLAB 提供了两个用于创建网格的函数:

  • meshgrid 创建与笛卡尔轴对齐的二维和三维网格。创建二维网格的语法为 [X,Y] = meshgrid(xgv, ygv),其中 xgv 是长度为 m 的向量,ygv 是长度为 n 的向量。meshgrid 通过复制 xgv 构成 n×m 矩阵 X,并通过复制 ygv 构成另一个 n×m 矩阵 YXY 表示网格点的坐标。X 的行与水平 X 轴对齐,Y 的列与负 Y 轴对齐。

  • ndgrid 创建与数组空间对齐的 N 维网格。在数组空间中,坐标区为行、列、页面等。调用语法为 [X1, X2, X3,...,Xn] = ndgrid(x1gv, x2gv, x3gv,...,xngv),其中 x1gv,x2gv,x3gv,...,xngv 是在各个维度涵盖网格的向量,X1,X2,X3,...,Xn 是可用于对多变量函数求值和用于多维插值的输出数组。

使用 meshgrid 可从两个向量 xgvygv 创建与二维轴对齐的网格。

xgv = [1 2 3];
ygv = [1 2 3 4 5];
[X,Y] = meshgrid(xgv, ygv)
X = 5×3

     1     2     3
     1     2     3
     1     2     3
     1     2     3
     1     2     3

Y = 5×3

     1     1     1
     2     2     2
     3     3     3
     4     4     4
     5     5     5

现在使用 ndgrid 从相同的两个向量 xgvygv 创建与二维空间对齐的网格。

[X1,X2] = ndgrid(xgv,ygv)
X1 = 3×5

     1     1     1     1     1
     2     2     2     2     2
     3     3     3     3     3

X2 = 3×5

     1     2     3     4     5
     1     2     3     4     5
     1     2     3     4     5

请注意,ndgridX1meshgridX 的转置。X2Y 同样如此。

对于给定的输入集,meshgridndgrid 函数将生成具有完全相同的坐标的网格。它们的输出之间的唯一差别是坐标数组的格式。绘制两个输出,可以看到它们是相同的。

figure()
[X1_ndgrid,X2_ndgrid] = ndgrid(1:3,1:5);
Z = zeros(3,5);
mesh(X1_ndgrid,X2_ndgrid,Z,'EdgeColor','black')
axis equal;

% Set the axis labeling and title
h1 = gca;
h1.XTick = [1 2 3];
h1.YTick = [1 2 3 4 5];
xlabel('ndgrid Output')

figure()
[X_meshgrid,Y_meshgrid] = meshgrid(1:3, 1:5);
mesh(X_meshgrid,Y_meshgrid,Z','EdgeColor','black')
axis equal;

% Set the axis labeling and title
h2 = gca;
h2.XTick = [1 2 3];
h2.YTick = [1 2 3 4 5];
xlabel('meshgrid Output')

根据网格的用途,可以选择其中的一种格式。MATLAB 中的一些函数可能要求您的数据采用 meshgrid 格式,而另一些函数可能要求 ndgrid 格式。

网格格式间的转换.  要将一个二维网格输出从 meshgrid 转换为 ndgrid 格式,请转置坐标矩阵:

[X_meshgrid,Y_meshgrid] = meshgrid(1:3, 1:5);
[X1_ndgrid,X2_ndgrid] = ndgrid(1:3,1:5);

isequal(X_meshgrid',X1_ndgrid)
ans =
     1
isequal(Y_meshgrid',X2_ndgrid)
ans =
     1
也可以使用 permute 函数。
isequal(permute(X_meshgrid,[2 1]),X1_ndgrid)
ans =
     1
要将一个三维 meshgrid 转换为 ndgrid,请转置坐标数组的每一页。对于给定的数组 my_arraypermute(my_array, [2 1 3]) 进行行列互换,实际效果是对每一页进行转置:
[X_meshgrid,Y_meshgrid,Z_meshgrid] = meshgrid(1:3, 1:5, [1 2]);
[X1_ndgrid,X2_ndgrid,X3_ndgrid] = ndgrid(1:3,1:5, [1 2]);

isequal(permute(X_meshgrid,[2 1 3]),X1_ndgrid)
ans =
     1

isequal(permute(Y_meshgrid,[2 1 3]),X2_ndgrid)
ans =
     1

isequal(permute(Z_meshgrid,[2 1 3]),X3_ndgrid)
ans =
     1

网格向量.  传递给网格函数的输入称为网格向量。网格向量隐式定义了网格。以两个向量 x1gv = (1:3)x2gv = (1:5) 为例。可以将这些向量视为沿 x1 方向的一组坐标和沿 x2 方向的一组坐标,如下所示:

每个箭头指向一个位置。使用这两个向量可以定义一组网格点,其中一组坐标由 x1gv 给定,另一组坐标由 x2gv 给定。在复制网格向量时,它们构成组成完整网格的两个坐标数组:

单调和非单调网格.  输入的网格向量可能是单调非单调的。单调向量所含的值在该维中递增,或在该维中递减。反之,非单调向量含有的值会上下波动。如果输入网格向量是非单调的,例如 [2 4 6 8 3 1],则 ndgrid 输出以下结果:

[X1,X2] = ndgrid([2 4 6 3 1])
X1 =
     2     2     2     2     2
     4     4     4     4     4
     6     6     6     6     6
     3     3     3     3     3
     1     1     1     1     1

X2 =
     2     4     6     3     1
     2     4     6     3     1
     2     4     6     3     1
     2     4     6     3     1
     2     4     6     3     1
如果要将网格传递给其他 MATLAB® 函数,网格向量应当是单调的。

均匀网格和非均匀网格.  均匀网格是给定维度中所有邻点均有相等间距的网格。例如,[X1, X2] = ndgrid([1 3 5 9],[11 13 15]) 是每一维度中间距均为两个单位的均匀网格。

没有必要让均匀网格中的间距在所有维度中均相等。例如,即使 X1X2 中的间距不同,[X1, X2] = ndgrid([1 2 3 4],[11 13 15]) 也被视为均匀网格。

任一维度中存在间距不一致的网格即会称为非均匀网格。例如,[X1, X2] = ndgrid([1 5 6 9],[11 13 15]) 便创建了一个非均匀网格,因为其间距沿第一维度变化。

均匀均匀非均匀

网格表示的类型

MATLAB 允许按以下三种方式之一表示网格:完整网格、简洁网格或默认网格。简洁网格和默认网格主要是为了方便使用和提高效率。

完整网格.  完整网格是一种以显式方式定义点的网格。ndgridmeshgrid 的输出定义一个完整网格。

简洁网格.  网格中每个点的显式定义与内存的消耗密切相关。简洁网格表示法无需完整网格的内存使用量。简洁网格表示法只存储网格向量,而不存储完整网格。(有关 griddedInterpolant 类如何使用简洁网格表示法的信息,请参阅 用 griddedInterpolant 类插值。)

默认网格.  在许多情况下分析数据时,既关注网格中点之间的距离,也关注点的值。例如,一个数据集可能表示某一地理区域中特定点的降雨量。这种情况下,既关注每个网格点的值,也关注点与其相邻点之间的距离。其他情况下,可能只关注给定点的值,而不关注相对距离。例如,在处理来自核磁共振成像 (MRI) 扫描的输入数据时,其中的点之间的距离是完全均匀的。这种情况下,只会关注点的值,而确信完全均匀的网格。这种情况下,默认网格表示法可派上用场。默认网格表示法将显式存储网格点处的值,隐式创建网格点的坐标。

网格逼近技术

在某些情况下,可能需要数据的逼近网格。通过选择一组合适的网格向量,可由标准的 MATLAB 网格得到理想化的逼近网格。例如,网格具有的点可以位于曲线上。如果数据是基于经纬度的,则可能出现这样的数据集:

这种情况下,虽然输入数据无法直接网格化,但是可以在合适的区间逼近网格直线:

也可以使用默认网格

简并网格.  简并网格是网格的一维或多维是单一维度的网格特例。单一维度可以是内部的,如本示例中的 7:7

[X1,X2,X3] = ndgrid(1:2:10,7:7,1:3:15);
单一维度也可以是后继维度:
[X1,X2,X3] = ndgrid(1:2:10,1:3:15,7:7);
如果要尝试取更大数据集的切片,可以创建一个简并网格。例如,您可能只想要分析三维 MRI 扫描的一个切片。这种情况下,需要来自多维网格的一个数据切片,例如以下图窗中的点式切片:

如果使用索引提取所需要的数据,则产生的网格是 X3 维中简并的网格:

[X1,X2,X3] = ndgrid(1:3);

X1_slice = X1(:,:,2)
X1_slice =
     1     1     1
     2     2     2
     3     3     3

X2_slice = X2(:,:,2)
X2_slice =
     1     2     3
     1     2     3
     1     2     3

X3_slice = X3(:,:,2)
X3_slice =
     2     2     2
     2     2     2
     2     2     2

数据网格化的概念对于理解 MATLAB 进行基于网格的插值的方式非常重要。

基于网格的插值

在基于网格的插值中,待插入的数据由有序网格表示。例如,准备在一个矩形平面曲面上以 1 厘米间隔垂直方向自顶向下、水平方向从左向右进行温度测量,视为二维网格化数据。基于网格的插值提供了获得网格点之间任意位置的温度的一种有效途径。

使用基于网格插值的好处

基于网格的插值大大节省了计算开销,因为网格化结构允许 MATLAB 非常迅速地定位查询点及其附近的相邻点。为了解其工作原理,以下面一维网格的点为例:

连接相邻点的直线表示网格的单元。第一个单元出现在 x = 1x = 3 之间,第二个出现在 x = 3x = 5 之间,依此类推。每个数表示网格中的一个坐标。如果要查询位于 x = 6 处的网格,必须使用插值,因为网格中未显式定义 6。由于此网格具有均匀间距 2,因此可以用一次整除 (6/2 = 3) 缩小查询点的位置范围。这就说明该点位于网格的第三个单元中。定位二维网格中的单元涉及到在每一维中执行一次此操作。此操作称为快速查找,仅当数据分布在均匀网格中时,MATLAB 才使用这项技术。

这种快速查找高效定位含有查询点 Xq 的单元。二分查找按如下方式进行:

  1. 定位网格中心点。

  2. Xq 与位于网格中心的点对比。

  3. 如果 Xq 小于在中心找到的点,则从搜索中排除所有大于中心点的网格点。同样,如果 Xq 大于在中心找到的点,则排除所有小于中心点的网格点。请注意,通过这样操作,我们已将搜索的点数减半了。

  4. 求出其余网格点的中心,从第 2 步重复执行,直到在查询的任何一侧剩下一个网格点。这两个点标记含有 Xq 的单元的边界。

以下示例说明了二分查找的强大功能。在电子化信用卡授权出现前,保护商户免遭信用卡欺诈购买行为的唯一方法是将每个客户的信用卡上的账号与“不良”账号名单进行比较。这类名单是装订好的册子,其中包含数以万计的按升序排列的卡号。对于一笔交易,要搜索包含 10,000 个账号的名单,需要进行多少次比较?结果表明,对于任意包含 n 个有序项的列表,最大比较次数不超过将列表对分的次数,即 log2(n)。因此,信用卡搜索需要的比较次数不超过 log2(10e3),即大约 13 次。考虑到执行顺序搜索时所需的比较次数,这是一个非常了不起的结果。

与此相反,假设一个涉及散点数据集的问题。

x = rand(20,1);
y = rand(20,1);
scatter(x,y)

求查询点邻近的点所需的操作次数要多得多。如果您的数据可以逼近为一个网格,则基于网格的插值可以节省大量计算和内存用量。

如果数据是分散的,则可以使用 内插散点数据 中详细描述的工具。

插值与拟合

MATLAB 中提供的插值方法可创建经过样本数据点的插值函数。如果要查询一个样本位置的插值函数,就需要取回位于该样本数据点的值。对比插值,曲线和曲面拟合算法则不需要通过样本数据点。

插值方法

基于网格的插值提供多种不同的插值方法。在选择插值方法时,切记有些方法比其他方法需要更多的内存或更长的计算时间。但是,需要权衡这些资源,以实现结果所需要的平滑度。下面的表格提供了每种方法的优点、取舍和要求。

方法说明连续性内存用量和性能要求
最近邻点在查询点插入的值是距样本网格点最近的值。 不连续
  • 最低内存要求

  • 最快计算时间

  • 每个维度需要 2 个网格点。

后邻点在查询点插入的值是下一个抽样网格点的值。不连续

其内存要求和计算时间与最近邻点法相同。

  • 仅用于一维插值。

  • 需要至少 2 个网格点。

前邻点在查询点插入的值是上一个抽样网格点的值。不连续

其内存要求和计算时间与最近邻点法相同。

  • 仅用于一维插值。

  • 需要至少 2 个网格点。

线性在查询点插入的值基于各维中邻点网格点处数值的线性插值。 C0
  • 比最近邻点需要更多内存。

  • 比最近邻点需要更多计算时间。

  • 每个维需要至少 2 个网格点。

Pchip在查询点插入的值基于邻点网格点处数值的保形分段三次插值。C1
  • 比线性插值方法需要更多内存。

  • 比线性插值方法需要更长的计算时间。

  • 仅用于一维插值。

  • 需要至少 4 个网格点。

三次在查询点插入的值基于各维中邻点网格点处数值的三次插值。C1
  • 比线性插值方法需要更多内存。

  • 比线性插值方法需要更长的计算时间。

  • 网格必须有均匀间距,但是每维中的间距不必相同。

  • 每维需要至少 4 个网格点。

修正 Akima在查询点插入的值基于次数最大为 3 的多项式的分段函数,使用各维中相邻网格点的值进行计算。为防过冲,已修正 Akima 公式。C1
  • 与样条插值具有相似的内存要求。

  • 比三次插值需要更长的计算时间,但通常少于样条插值的计算时间。

  • 每个维需要至少 2 个网格点。

样条曲线在查询点插入的值基于各维中邻点网格点处数值的三次插值。C2
  • 比三次插值需要更多内存。

  • 比三次插值需要更长的计算时间。

  • 每维需要 4 个网格点。

此图窗对各种一维数据插值方法进行了直观比较。

插值方法的对比

MATLAB 以多种方式提供与基于网格的插值相关的支持:

  • interp 系列函数:interp1interp2interp3interpn

  • griddedInterpolant 类。

interp 系列函数和 griddedInterpolant 支持 N 维基于网格的插值。但是,使用 griddedInterpolant 类比 interp 函数具有内存和性能方面的优势。而且,griddedInterpolant 类提供可配合任意维数的网格化数据使用的统一界面。

interp 系列函数的插值

interp1 函数

此示例说明如何使用 interp1 函数的 'pchip' 方法对一组样本值进行插值。

函数 interp1 执行一维插值。其最常见的形式为:

Vq = interp1(X,V,Xq,method)

其中,X 是坐标向量,V 向量包含这些坐标处的值。Xq 向量包含作为插入位置的查询点,可选的 method 方法指定四种插值方法之一:'nearest''linear''pchip''spline'

创建一组一维网格点 X 和对应的样本值 V

X = [1 2 3 4 5];
V = [12 16 31 10 6];

以 0.1 为间距在更小的区间上插值。

Xq = (1:0.1:5);
Vq = interp1(X,V,Xq,'pchip');

绘制样本和插入的值。

plot(X,V,'o');
hold on
plot(Xq,Vq,'-');
legend('samples','pchip');
hold off

以 interp1 进行一维外插

此示例说明如何使用 'extrap' 选项在样本点的域之外插值。

定义样本点和值。

X = [1 2 3 4 5];
V = [12 16 31 10 6];

指定查询点 Xq,这些查询点延伸到 X 的定义域以外。

Xq = (0:0.1:6);
Vq = interp1(X,V,Xq,'pchip','extrap');

绘制结果。

figure
plot(X,V,'o');
hold on
plot(Xq,Vq,'-');
legend('samples','pchip');
hold off

在另外的方法中,可以引入更多点,从而更好也控制外插区域中的行为。例如,可通过使用重复的值对域进行延伸,从而对曲线进行约束,使其在外插区域保持扁平。

X = [0 1 2 3 4 5 6];
V = [12 12 16 31 10 6 6];

指定进一步延伸到 X 的域之外的查询点 Xq

Xq = (-1:0.1:7);

使用 'pchip' 插值。您可以省略 'extrap' 选项,因为它是 'pchip''makima''spline' 方法的默认选项。

Vq = interp1(X,V,Xq,'pchip');

绘制结果。

figure
plot(X,V,'o');
hold on
plot(Xq,Vq,'-');
legend('samples','pchip');
hold off

interp2 函数

此示例说明如何使用 interp2 函数在更精细的网格上对粗采样的 peaks 函数进行插值。

interp2interp3 函数分别执行二维和三维插值,并且它们以 meshgrid 格式对网格进行插值。interp2 的调用语法具有以下一般形式:

Vq = interp2(X,Y,V,Xq,Yq,method)

其中,XY 是以 meshgrid 格式定义网格的坐标数组,V 是包含网格点处的值的数组。XqYq 是包含要插值的查询点坐标位置的数组。可以选择使用 method 指定四种插值方法之一:'nearest''linear''cubic''spline'

XY 构成的网格点必须单调递增并且符合 meshgrid 格式。

创建粗网格和对应的样本值。

[X,Y] = meshgrid(-3:1:3);
V = peaks(X,Y);

绘制样本值。

surf(X,Y,V)
title('Sample Grid');

生成更精细的网格用于插值。

[Xq,Yq] = meshgrid(-3:0.25:3);

在查询点位置使用 interp2 插值。

Vq = interp2(X,Y,V,Xq,Yq,'linear');

绘制结果。

surf(Xq,Yq,Vq);
title('Refined Grid');

interp3 函数

此示例说明如何使用 interp3 在单个查询点位置对三维函数进行插值,并将其与解析表达式所生成的值进行比较。

interp3 的工作方式与 interp2 相同,不同的是它采用两个额外参数:一个表示样本网格中的第三个维度,另一个表示查询点中的第三个维度,

Vq = interp3(X,Y,Z,V,Xq,Yq,Zq,method)

与使用 interp2 一样,提供给 interp3 的网格点必须单调递增,并且符合 meshgrid 格式。

定义用于生成 X、Y 和 Z 输入值的函数。

generatedvalues = @(X,Y,Z)(X.^2 + Y.^3 + Z.^4);

创建样本数据。

[X,Y,Z] = meshgrid((-5:.25:5));
V = generatedvalues(X,Y,Z);

在特定查询点位置插值。

Vq = interp3(X,Y,Z,V,2.35,1.76,0.23,'cubic')
Vq = 10.9765

Vq 与解析表达式所生成的值进行比较。

V_actual = generatedvalues(2.35,1.76,0.23)
V_actual = 10.9771

interpn 函数

此示例说明如何使用 interpn 函数的 'cubic' 方法,在更精细的网格上对粗采样的函数进行插值。

函数 interpnndgrid 格式的网格上执行 n 维插值。其最常见的形式为:

Vq = interpn(X1,X2,X3,...Xn,V,Y1,Y2,Y3,...,Yn,method)

其中,X1,X2,X3,...,Xn 是以 ndgrid 格式定义网格的坐标数组,V 是包含网格点处的值的数组。Y1,Y2,Y3,...,Yn 是包含要插值的查询点坐标位置的数组。可以选择使用 method 指定四种插值方法之一:'nearest''linear''cubic''spline'

X1,X2,X3,...Xn 构成的网格点必须单调递增并且符合 ndgrid 格式。

创建一组一维网格点和对应的样本值。

[X1,X2] = ndgrid((-5:1:5));
R = sqrt(X1.^2 + X2.^2)+ eps;
V = sin(R)./(R);

绘制样本值。

mesh(X1,X2,V)
title('Sample Grid');

创建更精细的网格用于插值。

[Y1,Y2] = ndgrid((-5:.5:5));

在更精细的网格上插值并绘制结果。

Vq = interpn(X1,X2,V,Y1,Y2,'cubic');
mesh(Y1,Y2,Vq)
title('Refined Grid');

interpn 还有另一个语法:Vq = interpn(V,ntimes,method),利用该语法可以在精度为样本网格整数倍的网格上插值。在上一段代码中,Y1Y2 查询了每个样本之间包含一个额外点的网格上的插值。以下代码演示了如何使用 ntimes=1 获得相同的结果。

使用 ntimes=1 在更精细的网格上插值。

Vq = interpn(V,1,'cubic');

绘制结果。

mesh(Vq)
title('Refined Grid with NTIMES');

请注意,该绘图的标度与前一示例不同。这是因为我们仅调用了 mesh 和传递了值。mesh 函数基于 Vq 的维度使用默认网格。两种情形下的输出值是相同的。

您也可以提供非均匀的查询点网格。如果您有兴趣以更高的密度查询网格区域内的插值,这将非常有用。以下代码说明如何完成此过程。

在偏置网格上插值。

[Y1, Y2] = ndgrid([-5 -4 -3 -2.5 -2 -1.5 -1.25 -1 -0.75 -0.5 -0.20 0]);
Vq = interpn(X1,X2,V,Y1,Y2,'cubic');

绘制结果。

mesh(Y1,Y2,Vq);
title('Biased Grid');

用 griddedInterpolant 类插值

interpn 函数相似,griddedInterpolant 类为 n 个维度中基于网格的插值提供单一接口。但是 griddedInterpolant 有以下额外优点:

  • 这有助于显著提高重复查询插值的性能。

  • 它提供了额外的性能改进和节省内存用量,因为将样本点存储为简洁网格

griddedInterpolant 接受符合 ndgrid 格式的样本数据。如果希望用 meshgrid 数据创建 griddedInterpolant,需要将数据转换成 ndgrid 格式。有关如何转换二维和三维 meshgrids 的演示,请参阅 将 meshgrid 数据转换为 ndgrid 格式

griddedInterpolant 类支持下列插值方法interpn 也支持这些方法):nearestlinearpchipcubicmakimaspline。但是 griddedInterpolant 以更小的开销提供更好的性能。

构建插值

interpolant 是用于执行插值的函数。通过调用 griddedInterpolant 构造函数和传递样本数据创建插值:网格和对应的样本值。如果希望覆盖默认的“线性”方法,也可以指定插值方法。调用语法具有下面的形式:

  • 对于一维插值,可以传递数据集 x 和含有对应值的相同长度的向量 v

    F = griddedInterpolant(x,v)

  • 对于更高维度,可以提供完整网格。X1,X2,...,Xn 将网格指定为一组 n n 维数组。这些数组符合 ndgrid 格式,大小与样本数组 V 相同。

     F = griddedInterpolant(X1,X2,...,Xn,V)

  • 如果已知相邻样本点之间的距离是均匀的,则可以通过只传递样本点 VgriddedInterpolant 创建一个默认网格。

     F = griddedInterpolant(V)

  • 也可以将样本数据的坐标指定为简洁网格。简洁网格由一组向量表示。这些向量然后被置于花括号内封装成元胞数组,例如 {x1g,x2g,...,xng} 其中向量 x1g,x2g,...,xng 定义每一维中的网格坐标。

     F = griddedInterpolant({x1g,x2g,...,xng},V)

  • 也可以用任何调用语法将插值方法指定为最终输入参数。本示例指定最近邻点插值。

     F = griddedInterpolant({x1g,x2g,x3g},V,'nearest')

查询插值

griddedInterpolantF 求值方式与调用函数相同。您可以将查询点分散或网格化,并按照下面的任何方式将查询点传递给 F

  • 您可以指定一个 mXn 矩阵 Xq,其中包含 n 维的 m 个散点。插入的值 Vq 以一个 mx1 向量的形式返回。

      Vq = F(Xq)

  • 您还可以将查询点指定为一系列长度为 m 的 n 列向量 x1q,x2q,...,xnq。这些向量表示 n 维的 m 个点。插入的值 Vq 以一个 mx1 向量的形式返回。

     Vq = F(x1q,x2q,...,xnq)

  • 您可以将查询点指定为一系列表示完整网格的 n 个 n 维数组。数组 X1q,X2q,...,Xnq 的大小完全相同,且符合 ndgrid 格式。插入的值 Vq 也将大小相同。

    Vq = F(X1q,X2q,...,Xnq)

  • 您也可以将查询点指定为简洁网格。x1gq,x2gq,...,xngq 是定义每维中网格点的向量。

    Vq = F({x1gq,x2gq,...,xngq})

    例如在二维空间中:

    Vq = F({(0:0.2:10),(-5:0.5:5)});

将 meshgrid 数据转换为 ndgrid 格式

griddedInterpolant 类接受 ndgrid 格式化的样本数据。如果要用 meshgrid 数据创建 griddedInterpolant,则应首先将其转换为 ndgrid 格式。

下面的示例概述将二维 meshgrid 数据转换成 ndgrid 格式的步骤。通过创建 meshgrid 和对应的样本值开始转换:

[X,Y] = meshgrid(-2:.1:2,-1:.1:1);
V=0.75*Y.^3-3*Y-2*X.^2;

要将 XYV 转换成 ndgrid 格式,请按下面的步骤操作:

  1. 转置网格中的每个数组以及样本数据。

    X=X';
    Y=Y';
    V=V';
  2. 现在创建插值。

    F = griddedInterpolant(X,Y,V);

要转换三维 meshgrid,请使用 permute 函数。同样地,首先创建 meshgrid 和对应的样本值:

[X,Y,Z] = meshgrid(-5:5,-3:3,-10:10);
V = X.^3 + Y.^2 + Z;

要将 XYZV 转换成 ndgrid 格式,请按下面的步骤操作:

  1. 使用 permute 函数互换每个数组的行和列。实际效果是转置每一页。

    P = [2 1 3];
    X = permute(X,P);
    Y = permute(Y,P);
    Z = permute(Z,P);
    V = permute(V,P);

  2. 现在创建插值。

    F = griddedInterpolant(X,Y,Z,V);

一维中的 griddedInterpolant

本示例显示如何使用 griddedInterpolant 及三次插值方法创建和绘制一个一维插值。

创建粗略网格和样本值。

X = [1 2 3 4 5];
V = [12 6 15 9 6];

使用三次插值方法构建 griddedInterpolant

F = griddedInterpolant(X,V,'cubic')
F = 
  griddedInterpolant with properties:

            GridVectors: {[1 2 3 4 5]}
                 Values: [12 6 15 9 6]
                 Method: 'cubic'
    ExtrapolationMethod: 'cubic'

GridVectors 属性包含指定样本值 V 的坐标的简洁网格。Method 属性指定插值方法。请注意,我们在创建 F 时已指定 'cubic'。如果省略 Method 参数,则默认插值方法 linear 将被赋给 F

您可以按照访问 F 中的字段的方式来访问 struct 的任意属性。

F.GridVectors;          % Displays the grid vectors as a cell array
F.Values;               % Displays the sample values
F.Method;               % Displays the interpolation method

以 0.1 为间距在更小的区间上插值。

Xq = (1:0.1:5);
Vq = F(Xq);

绘制结果。

plot(X,V,'o');
hold on
plot(Xq,Vq,'-');
legend('samples','Cubic Interpolation');

二维中的 griddedInterpolant

本示例显示如何使用 griddedInterpolant 来创建和绘制一个二维插值。

在二维和更高维情况下,可以将样本坐标指定为一个 ndgrid、简洁网格或默认网格。在此示例中,我们将提供一个 ndgrid

创建粗略网格和样本值。

[X,Y] = ndgrid(-1:.3:1,-2:.3:2);
V = 0.75*Y.^3 - 3*Y - 2*X.^2;

构建 griddedInterpolant

F = griddedInterpolant(X,Y,V,'spline');

以 0.1 为间距在更小的区间上插值。

[Xq,Yq] = ndgrid(-1:.1:1,-2:.1:2);
Vq = F(Xq,Yq);

绘制结果。

figure()
surf(X,Y,V);
view(65,60)
title('Sample Data');

figure()
surf(Xq,Yq,Vq);
view(65,60)
title('Refined with Spline');

三维中的 griddedInterpolant

本示例显示如何创建一个三维插值,并在切片平面上求值,以便绘制该平面上的值。

创建完整网格和样本值。

[X,Y,Z] = ndgrid((-5:2:5));
V = X.^3 + Y.^2 + Z.^2;

构建 griddedInterpolant

F = griddedInterpolant(X,Y,Z,V,'cubic');

由于我们创建了完整网格来生成样本值,在将其传递给 griddedInterpolant 时未丢失任何信息。但是在实际情况中,常常将样本数据从磁盘加载到 MATLAB 中。简洁网格在这类情况下非常有利,因为它允许在内存方面节省得多的方式指定整个网格。如果我们已将 V 加载到 MATLAB 中,而没有从完整网格计算,则肯定是在工作区中创建了简洁网格以节省内存。例如,

gv = {(-5:2:5),(-5:2:5),(-5:2:5)};
F = griddedInterpolant(gv,V,'cubic');

现在我们以 0.25 的间距在 Z = 2 处的平面上进行了插值。

[Xq,Yq,Zq] = ndgrid((-5:.25:5),(-5:.25:5),2:2);
Vq = F(Xq,Yq,Zq);

绘制结果。

surf(Xq,Yq,Vq);
title('Refined with Linear Interpolation');

四维中的 griddedInterpolant

本示例将会创建一个四维插值并进行单点求值。

  1. 创建粗略网格和样本值。

    [X1,X2,X3,X4] = ndgrid((-5:2:5));
    V = X1.^3 + X2.^2 + X3.^2 +X4;

  2. 构建 griddedInterpolant

    F = griddedInterpolant(X1,X2,X3,X4,V,'linear');

  3. 查询单点处的 griddedInterpolant

    Vq = F([-3.2 2.1 4.7 -1.3])

    MATLAB 输出以下结果:

    ans =
    
      -10.1000

使用 griddedInterpolant 的其他方式

根据查询点的排列情况,或许某种求值语法较之其他语法更加适合。例如,创建以下插值:

[X,Y] = ndgrid(-1:.25:1,-2:.25:2);
V = 0.75*Y.^3-3*Y-2*X.^2;
F = griddedInterpolant(X,Y,V);

使用完整网格来查询 F,以给出网格点处的值:

[Xq,Yq] = ndgrid(-1:.1:0,-2:.1:0);
Vq = F(Xq,Yq);

也可以使用简洁网格格式在相同网格上进行插值:

gvq = {-1:.1:0,-2:.1:0};
Vq = F(gvq);

或者可以查询单个点:

Vq =  F(.315,.738)

将返回:

Vq =

   -2.1308

或一组随机散点:

rng('default')
Vq = F(rand(3,2))

将返回:

Vq =

   -3.4919
   -3.3557
   -0.3515

也可以检查 F 中的 Values

 F.Values(1,3)

将返回:

 ans =

   -0.0313

或者可以替换 Values 数组:

F.Values = 2*V;

可以动态编辑 F 中的属性。例如,可以按如下方式替换插值方法:

 F.Method = 'cubic';

也可以替换 F 中的 GridVectors。首先,检查 GridVectors

gv = F.GridVectors;
gv{1}
gv 是一个元胞数组,gv{1} 显示第一个网格向量:
ans =

   -1.0000   -0.7500   -0.5000   -0.2500    0    0.2500    0.5000    0.7500    1.0000

现在通过创建新的元胞数组 new_gv 替换 F 中的 GridVectors

new_gv = {(0:0.3:1),(0:0.3:1)};
F.GridVectors = new_gv;