29.1 一维插值

Octave 支持多种一维插值方法,本节将介绍其中大部分方法。多项式插值散点数据插值 描述了其他方法。

 
yi = interp1 (x, y, xi)
yi = interp1 (y, xi)
yi = interp1 (…, method)
yi = interp1 (…, extrap)
yi = interp1 (…, "left")
yi = interp1 (…, "right")
pp = interp1 (…, "pp")

一维插值。

对输入数据进行插值,以确定 yi 在点 xi 处的值。若未指定 x,则将其视为 y 的索引 (1:length (y))。如果 y 是矩阵或 N 维数组,则对 y 的每一列分别执行插值。

插值方法 method 可以是以下之一:

"nearest"

返回最近邻点的值。

"previous"

返回前一个邻点的值。

"next"

返回后一个邻点的值。

"linear"(默认)

基于最近邻点的线性插值。

"pchip"

分段三次 Hermite 插值多项式——保持形状的插值,具有光滑的一阶导数。

"cubic"

三次插值(与 "pchip" 相同)。

"spline"

三次样条插值——在整个曲线上具有光滑的一阶和二阶导数。

在上述任何方法名称前添加 "*",可强制 interp1 假设 x 是均匀间隔的,此时只会引用 x(1)x(2)。这通常更快,且绝不会更慢。默认方法为 "linear"

如果 extrap 是字符串 "extrap",则使用当前 method 对端点之外的值进行外推。如果 extrap 是一个数值,则用该数值替换端点之外的值。未指定时,extrap 默认为 NA

如果指定了字符串参数 "pp",则不应提供 xi,此时 interp1 返回一个分段多项式对象。该对象随后可与 ppval 配合使用来计算插值。存在如下等价关系:ppval (interp1 (x, y, method, "pp"), xi) == interp1 (x, y, xi, method, "extrap")

x 中的重复点用于指定不连续的插值函数。最多允许有 2 个连续点具有相同的值。如果 x 是递增的,默认的不连续插值函数是右连续的。如果 x 是递减的,默认的不连续插值函数是左连续的。可以通过使用选项 "left""right" 来指定插值函数的连续性条件,分别选择左连续或右连续的插值函数。不连续插值仅允许用于 "nearest""linear" 方法;在所有其他情况下,x 的值必须唯一。

interp1 的使用示例如下:

xf = [0:0.05:10];
yf = sin (2*pi*xf/5);
xp = [0:10];
yp = sin (2*pi*xp/5);
lin = interp1 (xp, yp, xf);
near = interp1 (xp, yp, xf, "nearest");
pch = interp1 (xp, yp, xf, "pchip");
spl = interp1 (xp, yp, xf, "spline");
plot (xf,yf,"r", xf,near,"g", xf,lin,"b", xf,pch,"c", xf,spl,"m",
      xp,yp,"r*");
legend ("original", "nearest", "linear", "pchip", "spline");

另请参阅: pchip, spline, interpft, interp2, interp3, interpn

各种插值方法之间存在一些重要差异。"spline" 方法强制要求插值函数在整个区间上具有连续的一阶和二阶导数,而其他方法则没有此要求。这意味着 "spline" 方法的结果通常更为平滑。如果被插值的函数本身是光滑的,那么 "spline" 将给出优秀的结果。然而,如果待评估的函数在某种程度上是不连续的,那么 "pchip" 插值可能会给出更好的结果。

这可以通过以下代码来演示:

t = -2:2;
dt = 1;
ti =-2:0.025:2;
dti = 0.025;
y = sign (t);
ys = interp1 (t,y,ti,"spline");
yp = interp1 (t,y,ti,"pchip");
ddys = diff (diff (ys)./dti) ./ dti;
ddyp = diff (diff (yp)./dti) ./ dti;
figure (1);
plot (ti,ys,"r-", ti,yp,"g-");
legend ("spline", "pchip", 4);
figure (2);
plot (ti,ddys,"r-", ti,ddyp,"g-");
legend ("spline", "pchip", 4);

结果如 图 29.1图 29.2 所示。

interp1

图 29.1: splinepchip 插值结果的比较

interp1d2

图 29.2: splinepchip 插值的二阶导数比较

 
y = interpft (x, n)
y = interpft (x, n, dim)

使用傅里叶方法进行一维插值。

通过傅里叶变换将 x 重新采样为 n 个点。假定 x 中的数据是等距采样的。如果 x 是矩阵或 N 维数组,则对 x 的每一列分别执行插值。

如果指定了 dim,则沿维度 dim 进行插值。

interpft 假定插值函数是周期性的,因此会对插值结果的端点做出相应假设。

另请参阅: interp1

傅里叶插值有两个显著的局限性。首先,它假定函数信号是周期性的,因此非周期信号在边界处表现不佳。其次,信号及其插值都需要在等距点上采样。interpft 的使用示例如下:

t = 0 : 0.3 : pi; dt = t(2)-t(1);
n = length (t); k = 100;
ti = t(1) + [0 : k-1]*dt*n/k;
y = sin (4*t + 0.3) .* cos (3*t - 0.1);
yp = sin (4*ti + 0.3) .* cos (3*ti - 0.1);
plot (ti, yp, "g", ti, interp1 (t, y, ti, "spline"), "b", ...
      ti, interpft (y, k), "c", t, y, "r+");
legend ("sin(4t+0.3)cos(3t-0.1)", "spline", "interpft", "data");

该示例展示了傅里叶插值对非周期函数的不良表现,如 图 29.3 所示。

interpft

图 29.3: interp1interpft 在非周期数据上的比较

此外,作为 interp1 函数基础的支持函数 splinelookup 也可以直接调用。

 
pp = spline (x, y)
yi = spline (x, y, xi)

返回点 xy 的三次样条插值函数。

当使用两个参数调用时,返回一个分段多项式 pp,可配合 ppval 在特定点处计算多项式的值。

当使用第三个输入参数调用时,spline 在点 xi 处计算样条值。第三种调用形式 spline (x, y, xi) 等价于 ppval (spline (x, y), xi)

变量 x 必须是长度为 n 的向量。

y 可以是向量或数组。如果 y 是向量,则其长度必须为 nn + 2。如果 y 的长度为 n,则使用 "not-a-knot"(非结点)端点条件。如果 y 的长度为 n + 2,则向量 y 的第一个值和最后一个值分别是三次样条在端点处的一阶导数值。

如果 y 是数组,则 y 的大小必须为 [s1, s2, …, sk, n][s1, s2, …, sk, n + 2]。数组内部会被重塑为一个矩阵,其前导维度为 s1 * s2 * … * sk,然后对该矩阵的每一行分别进行处理。请注意,这与 interp1 的处理方式恰好相反,但这是为了与 MATLAB 保持兼容。

另请参阅: pchip, ppval, mkpp, unmkpp


版权所有 © 2024-2026 Octave中文网

ICP备案/许可证号:黑ICP备2024030411号-2