插值、导数和积分

本部分探讨了插值和数值微积分的相互关联的数学表达式。

插值

插值用于在已知控制点集之间构建新的数据点。预测新数据点的能力允许沿控制点定义的曲线进行采样。

下面描述的所有插值函数都返回一个插值函数,该函数可以传递给利用采样功能的其他函数。

如果直接返回,则插值函数将返回一个包含每个控制点预测的数组。这在loess插值的情况下很有用,该插值首先平滑控制点,然后插值平滑的点。所有其他插值函数都只返回原始控制点,因为插值预测通过原始控制点的曲线。

有不同的插值算法,它们将导致沿曲线产生不同的预测。数学表达式库当前支持以下插值函数

  • lerp:线性插值预测通过每个控制点并形成控制点之间直线的点。

  • spline:样条插值预测通过每个控制点并形成控制点之间平滑曲线的点。

  • akima:Akima 样条插值类似于样条插值,但对异常值稳定。

  • loess:Loess 插值首先执行非线性局部回归以平滑原始控制点。然后使用样条插值平滑的控制点。

沿曲线采样

更好地理解插值的一种方法是可视化沿曲线采样意味着什么。下面的示例通过在特定 x 轴范围之间对曲线进行采样,对曲线的特定区域进行放大。

interpolate1

上面的可视化首先创建两个包含 x 和 y 轴点的数组。请注意,x 轴范围从 0 到 9。然后将 akimasplinelerp 函数应用于向量,以创建三个插值函数。

然后从 0 到 3 之间的均匀分布中绘制 500 个随机样本。这些是新的放大 x 轴点,介于 0 和 3 之间。请注意,我们正在对曲线的特定区域进行采样。

然后使用 predict 函数预测所有三个插值函数的采样 x 轴的 y 轴点。最后,将所有三个预测向量与采样 x 轴点一起绘制。

红线是 lerp 插值,蓝线是 akima,紫线是 spline 插值。您可以看到它们在控制点之间产生不同的曲线。

平滑插值

loess 函数是一个平滑插值器,这意味着它不会派生出通过原始控制点的函数。相反,loess 函数返回一个平滑原始控制点的函数。

一种称为局部回归的技术用于计算平滑曲线。局部回归邻域的大小可以调整,以控制新曲线与原始控制点的接近程度。

loess 函数传递 x 和 y 轴,并为数据拟合平滑曲线。如果只提供一个数组,则将其视为 y 轴,并为 x 轴生成一个序列。

下面的示例显示了 loess 函数用于对月度时间序列进行建模。在示例中,timeseries 函数用于生成股票代码 AMZN 的平均收盘价的月度时间序列。然后将时间序列中的 date_dtavg(close_d) 字段向量化并存储在变量 xy 中。然后将 loess 函数应用于包含平均收盘价的 y 向量。bandwidth 命名参数指定用于计算局部回归的数据集的百分比。loess 函数返回平滑数据点的拟合模型。

然后使用 zplot 函数绘制 xyy1 变量。

loess

导数

函数的导数测量 y 值相对于 x 值变化率的变化率。

derivative 函数可以计算上面描述的任何插值函数的导数。每个插值函数将产生不同的导数,以匹配函数的特征。

一阶导数(速度)

一个简单的示例展示了如何使用 derivative 函数来计算变化率或速度

在示例中,创建了两个向量,一个表示小时数,另一个表示行驶的英里数。然后使用 lerp 函数创建 hoursmiles 向量的线性插值。然后将 derivative 函数应用于线性插值。然后使用 zplot 在 x 轴上绘制hours,在 y 轴上绘制 miles,并在每个 x 轴点绘制 derivative 作为 mph

derivative

请注意,miles_traveled 线的斜率为 10,直到第 5 小时变为 50。mph 线是导数,它可视化miles_traveled 线的速度

还要注意,导数是沿着直线计算的,显示了从一点到下一点的立即变化。这是因为线性插值 (lerp) 用作插值函数。如果使用了 splineakima 函数,它将产生具有圆形曲线的导数。

二阶导数(加速度)

一阶导数表示速度,而二阶导数表示加速度。二阶导数是一阶导数的导数。

以下示例基于第一个示例并添加了二阶导数。请注意,二阶导数 d2 是通过将导数函数应用于一阶导数的线性插值来获得的。

二阶导数在图表上绘制为加速度

derivatives

请注意,加速度线为 0,直到mph 线从 10 增加到 50。此时,加速度线移动到 40。随着mph 线保持在 50,加速度线下降到 0。

价格速度

以下示例显示如何绘制由 timeseries 函数生成的时间序列的 derivative。在该示例中,为股票代码 amzn 的平均收盘价生成月度时间序列。avg(close) 列使用线性插值 (lerp) 进行矢量化和插值。然后使用 zplot 函数绘制时间序列的导数。

derivative2

请注意,导数图清楚地显示了股票价格随时间变化的速率。

积分

积分是曲线下方体积的度量。integral 函数计算曲线的累积积分或插值曲线的特定范围的积分。与 derivative 函数一样,integral 函数在插值函数上运行。

单积分

如果 integral 函数传递了 startend 范围,它将计算该特定范围内的曲线下方体积。

在以下示例中,integral 函数计算整个曲线范围(0 到 10)的积分。请注意,integral 函数传递插值曲线和开始和结束范围,并返回该范围的积分。

let(x=array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20),
    y=array(0, 1, 2, 3, 4, 5.7, 6, 7, 7, 7,6, 7, 7, 7, 6, 5, 5, 3, 2, 1, 0),
    curve=loess(x, y, bandwidth=.3),
    integral=integral(curve,  0, 10))

当此表达式发送到 /stream 处理程序时,它会响应

{
  "result-set": {
    "docs": [
      {
        "integral": 45.300912584519914
      },
      {
        "EOF": true,
        "RESPONSE_TIME": 0
      }
    ]
  }
}

累积积分图

如果 integral 函数传递单个插值曲线,它将返回该曲线的累积积分向量。累积积分向量包含每个 x 轴点的累积积分计算。累积积分通过计算每个 x 轴点和 first x 轴点之间的范围的积分来计算。在上面的示例中,这意味着计算一个积分向量,如下所示

let(x=array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20),
    y=array(0, 1, 2, 3, 4, 5.7, 6, 7, 7, 7,6, 7, 7, 7, 6, 5, 5, 3, 2, 1, 0),
    curve=loess(x, y, bandwidth=.3),
    integrals=array(0, integral(curve, 0, 1), integral(curve, 0, 2), integral(curve, 0, 3), ...)

累积积分图可视化每个 x 轴点下方曲线的累积体积。

以下示例显示了由 timeseries 函数生成的时间序列的累积积分图。在该示例中,为股票代码 amzn 的平均收盘价生成月度时间序列。avg(close) 列使用 spline 进行矢量化和插值。

然后使用 zplot 函数绘制时间序列的累积积分。

integral

上图可视化了曲线下方体积,因为 AMZN 股票价格随时间变化。由于此图是累积的,因此股票价格时间序列下方体积随时间保持不变,将具有正的 线性斜率。价格上涨的股票将具有 凹面形状,而价格下跌的股票将具有 凸面形状。

在这个特定示例中,积分图随着时间的推移变得更加 凹面,显示出股票价格的加速上涨。

双三次样条

bicubicSpline 函数可用于插值和预测数据网格内的任意值。

一个简单的例子将使这一点更加清晰

let(years=array(1998, 2000, 2002, 2004, 2006),
    floors=array(1, 5, 9, 13, 17, 19),
    prices = matrix(array(300000, 320000, 330000, 350000, 360000, 370000),
                    array(320000, 330000, 340000, 350000, 365000, 380000),
                    array(400000, 410000, 415000, 425000, 430000, 440000),
                    array(410000, 420000, 425000, 435000, 445000, 450000),
                    array(420000, 430000, 435000, 445000, 450000, 470000)),
    bspline=bicubicSpline(years, floors, prices),
    prediction=predict(bspline, 2003, 8))

在此示例中,使用三次样条插值法对房地产数据矩阵进行插值。矩阵的每一行代表特定的年份。矩阵的每一列代表建筑物的楼层。数字网格是每一年和楼层的公寓平均售价。例如,2002 年,9 楼的平均售价为415000(第 3 行,第 3 列)。

然后使用bicubicSpline函数对网格进行插值,并使用predict函数预测 2003 年、8 楼的值。请注意,该矩阵不包括 2003 年、8 楼的数据点。bicubicSpline函数基于矩阵中周围的数据创建该数据点

{
  "result-set": {
    "docs": [
      {
        "prediction": 418279.5009328358
      },
      {
        "EOF": true,
        "RESPONSE_TIME": 0
      }
    ]
  }
}