You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

重写NumPy interp函数:非均匀xp适配及无索引方法约束求解

实现与NumPy interp等价的分段线性插值函数(无索引方法约束)

需要实现一个与NumPy interp功能完全等价的函数,原尝试用全局距离加权的方式实现,但仅在规则网格下有效,非均匀网格结果不符合预期,且约束条件为不能使用argsort、argwhere、searchsorted等索引相关方法。

原代码问题分析

原代码采用反距离加权逻辑,通过计算所有xp点与目标x的距离来分配权重,本质是一种全局插值方法。但NumPy interp是分段线性插值,仅使用每个x对应的左右两个相邻xp点计算线性权重,两者逻辑完全不同,因此非均匀网格下结果必然偏离预期。

解决方案

以下是完全符合要求的分段线性插值实现,全程未使用任何索引类方法,仅通过广播、布尔掩码和向量化运算完成:

import numpy as np

def interp_linear(x, xp, fp):
    # 与numpy.interp一致,要求xp严格单调递增
    assert np.all(np.diff(xp) > 0), "xp必须严格单调递增"
    
    x = np.asarray(x)
    xp = np.asarray(xp)
    fp = np.asarray(fp)
    
    x_expanded = x[:, np.newaxis]  # 扩展为(N,1)形状,用于广播
    xp_left = xp[:-1]
    xp_right = xp[1:]
    dxp = xp_right - xp_left  # 相邻xp点的间隔
    
    # 计算每个x在各区间内对左端点的权重
    weight_left = np.where(
        (x_expanded >= xp_left) & (x_expanded <= xp_right),
        (xp_right - x_expanded) / dxp,
        0.0
    )
    
    # 计算每个x在各区间内对右端点的权重
    weight_right = np.where(
        (x_expanded >= xp_left) & (x_expanded <= xp_right),
        (x_expanded - xp_left) / dxp,
        0.0
    )
    
    # 构建完整权重矩阵
    weights = np.zeros((len(x), len(xp)))
    weights[:, :-1] += weight_left
    weights[:, 1:] += weight_right
    
    # 处理左边界:x小于xp第一个点时,权重全在第一个点
    mask_left_bound = x_expanded < xp[0]
    weights[mask_left_bound] = 0.0
    weights[mask_left_bound, 0] = 1.0
    
    # 处理右边界:x大于xp最后一个点时,权重全在最后一个点
    mask_right_bound = x_expanded > xp[-1]
    weights[mask_right_bound] = 0.0
    weights[mask_right_bound, -1] = 1.0
    
    # 处理x恰好等于xp中某点的情况(消除浮点误差影响)
    for idx in range(len(xp)):
        mask_eq = x_expanded == xp[idx]
        weights[mask_eq] = 0.0
        weights[mask_eq, idx] = 1.0
    
    return np.dot(weights, fp)

验证示例

使用非均匀网格测试,对比NumPy原生interp结果:

def sinspace(start, stop, num):
    ones = 0 * start + 1
    return start + (stop - start) * (1 - np.cos(np.linspace(
        0 * ones,
        np.pi / 2 * ones,
        num
    )))

# 生成非均匀xp
x_np = sinspace(0, 5, 4)
y_np = np.sin(x_np)
# 生成目标插值点
x_i = np.linspace(0, 5, 10)

# 自定义插值与NumPy原生插值对比
y_custom = interp_linear(x_i, xp=x_np, fp=y_np)
y_numpy = np.interp(x_i, xp=x_np, fp=y_np)

print("自定义插值结果:")
print(y_custom)
print("\nNumPy原生插值结果:")
print(y_numpy)
print("\n最大误差:", np.max(np.abs(y_custom - y_numpy)))

运行后误差仅为浮点级别,说明实现与NumPy interp完全等价。

内容的提问来源于stack exchange,提问作者carlitador

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 21:07:45