Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何使用scipy执行二维插值?_Python_Scipy_Interpolation - Fatal编程技术网

Python 如何使用scipy执行二维插值?

Python 如何使用scipy执行二维插值?,python,scipy,interpolation,Python,Scipy,Interpolation,本问答旨在作为关于使用scipy的二维(和多维)插值的规范(-ish)。经常会有关于各种多维插值方法的基本语法的问题,我希望也能澄清这些问题。 我有一组分散的二维数据点,我想将它们绘制成一个漂亮的曲面,最好使用matplotlib.pyplot中的contourf或plot\u surface。如何使用scipy将二维或多维数据插值到网格 我找到了scipy.interpolate子包,但在使用interp2d或bisplrep或griddata或rbfipolator(或旧的Rbf)时,我总是

本问答旨在作为关于使用scipy的二维(和多维)插值的规范(-ish)。经常会有关于各种多维插值方法的基本语法的问题,我希望也能澄清这些问题。

我有一组分散的二维数据点,我想将它们绘制成一个漂亮的曲面,最好使用
matplotlib.pyplot
中的
contourf
plot\u surface
。如何使用scipy将二维或多维数据插值到网格


我找到了
scipy.interpolate
子包,但在使用
interp2d
bisplrep
griddata
rbfipolator
(或旧的
Rbf
)时,我总是会出错。这些方法的正确语法是什么?

免责声明:我在写这篇文章时主要考虑了语法方面的考虑和一般行为。我不熟悉所描述的方法的内存和CPU方面,而我的目的是在那些有合理的小数据集的人,这样插值的质量可以是主要考虑的方面。我知道,在处理非常大的数据集时,性能更好的方法(即
griddata
rbfipolator
没有
邻居
关键字参数)可能不可行

请注意,此答案使用中引入的新类。有关遗留类,请参见

我将比较三种多维插值方法(/样条,和)。我将使它们服从两种插值任务和两种基本函数(从中插值的点)。具体示例将演示二维插值,但可行的方法适用于任意维。每种方法都提供各种插值;在所有情况下,我都会使用三次插值(或接近1的东西)。需要注意的是,无论何时使用插值,都会引入与原始数据相比的偏差,并且使用的特定方法会影响最终产生的工件。始终注意这一点,并负责任地插入

这两个插值任务将是

  • 上采样(输入数据在矩形网格上,输出数据在更密集的网格上)
  • 将散乱数据插值到规则网格上
  • 这两个函数(在[-1,1]x[-1,1]中的域
    [x,y]上)将

  • 平滑友好的函数:
    cos(pi*x)*sin(pi*y)
    ;范围在
    [-1,1]
  • 一个邪恶的(特别是非连续的)函数:
    x*y/(x^2+y^2)
    ,在原点附近的值为0.5;范围在
    [-0.5,0.5]
  • 以下是它们的外观:

    我将首先演示这三种方法在这四个测试下的行为,然后详细介绍这三种方法的语法。如果您知道应该从方法中得到什么,您可能不想浪费时间学习它的语法(看看您,
    interp2d

    测试数据 为了明确起见,下面是我用来生成输入数据的代码。虽然在这个特定的例子中,我显然知道数据背后的函数,但我将只使用它来生成插值方法的输入。我使用numpy是为了方便(主要是为了生成数据),但仅使用scipy也足够了

    import numpy as np
    import scipy.interpolate as interp
    
    # auxiliary function for mesh generation
    def gimme_mesh(n):
        minval = -1
        maxval =  1
        # produce an asymmetric shape in order to catch issues with transpositions
        return np.meshgrid(np.linspace(minval, maxval, n),
                           np.linspace(minval, maxval, n + 1))
    
    # set up underlying test functions, vectorized
    def fun_smooth(x, y):
        return np.cos(np.pi*x) * np.sin(np.pi*y)
    
    def fun_evil(x, y):
        # watch out for singular origin; function has no unique limit there
        return np.where(x**2 + y**2 > 1e-10, x*y/(x**2+y**2), 0.5)
    
    # sparse input mesh, 6x7 in shape
    N_sparse = 6
    x_sparse, y_sparse = gimme_mesh(N_sparse)
    z_sparse_smooth = fun_smooth(x_sparse, y_sparse)
    z_sparse_evil = fun_evil(x_sparse, y_sparse)
    
    # scattered input points, 10^2 altogether (shape (100,))
    N_scattered = 10
    rng = np.random.default_rng()
    x_scattered, y_scattered = rng.random((2, N_scattered**2))*2 - 1
    z_scattered_smooth = fun_smooth(x_scattered, y_scattered)
    z_scattered_evil = fun_evil(x_scattered, y_scattered)
    
    # dense output mesh, 20x21 in shape
    N_dense = 20
    x_dense, y_dense = gimme_mesh(N_dense)
    
    平滑函数与上采样 让我们从最简单的任务开始。以下是如何从形状为
    [6,7]
    的网格向上采样到形状为
    [20,21]
    的网格,以实现平滑测试功能:

    尽管这是一项简单的任务,但输出之间已经存在细微的差异。乍一看,这三种产出都是合理的。根据我们对底层函数的先验知识,有两个特性需要注意:中间的
    griddata
    最扭曲数据。注意图的
    y==-1
    边界(距离
    x
    标签最近):函数应严格为零(因为
    y==-1
    是平滑函数的节点线),但
    griddata
    的情况并非如此。还要注意图的
    x==-1
    边界(后面,左边):基础函数在
    [-1,-0.5]
    处有一个局部最大值(意味着边界附近的零梯度),但是
    griddata
    输出清楚地显示了该区域的非零梯度。效果是微妙的,但它仍然是一种偏见

    邪恶函数与上采样 更难的任务是对邪恶函数执行上采样:

    三种方法之间开始出现明显的差异。查看曲面图,在
    interp2d
    的输出中出现明显的伪极值(请注意绘制曲面右侧的两个凸起)。而
    griddata
    rbf插值器
    乍一看似乎产生了类似的结果,在
    [0.4,-0.4]
    附近产生了基础函数中缺少的局部极小值

    然而,
    rbf插值器
    有一个关键的优势:它尊重基础函数的对称性(当然,样本网格的对称性也使之成为可能)。
    griddata
    的输出破坏了采样点的对称性,而在平滑情况下,采样点的对称性已经很弱

    光滑函数与散乱数据 通常需要对分散的数据执行插值。因此,我希望这些测试更加重要。如上所示,在感兴趣的域中伪均匀地选择样本点。在实际场景中,每个测量可能会有额外的噪声,并且应该考虑是否将原始数据插入到初始信息中是有意义的。
    # reminder: x_sparse and y_sparse are of shape [6, 7] from numpy.meshgrid
    zfun_smooth_interp2d = interp.interp2d(x_sparse, y_sparse, z_sparse_smooth, kind='cubic')   # default kind is 'linear'
    # reminder: x_dense and y_dense are of shape (20, 21) from numpy.meshgrid
    xvec = x_dense[0,:] # 1d array of unique x values, 20 elements
    yvec = y_dense[:,0] # 1d array of unique y values, 21 elements
    z_dense_smooth_interp2d = zfun_smooth_interp2d(xvec, yvec)   # output is (20, 21)-shaped array
    
    kind = 'cubic'
    if kind == 'linear':
        kx = ky = 1
    elif kind == 'cubic':
        kx = ky = 3
    elif kind == 'quintic':
        kx = ky = 5
    # bisplrep constructs a spline representation, bisplev evaluates the spline at given points
    bisp_smooth = interp.bisplrep(x_sparse.ravel(), y_sparse.ravel(),
                                  z_sparse_smooth.ravel(), kx=kx, ky=ky, s=0)
    z_dense_smooth_bisplrep = interp.bisplev(xvec, yvec, bisp_smooth).T  # note the transpose
    
    if not rectangular_grid:
        # TODO: surfit is really not meant for interpolation!
        self.tck = fitpack.bisplrep(x, y, z, kx=kx, ky=ky, s=0.0)
    
    tx, ty, c, o = _fitpack._surfit(x, y, z, w, xb, xe, yb, ye, kx, ky,
                                    task, s, eps, tx, ty, nxest, nyest,
                                    wrk, lwrk1, lwrk2)