What to do if I want 3D spline/smooth interpolation of random unstructured data?

前端 未结 1 1312
無奈伤痛
無奈伤痛 2020-12-14 02:47

I was inspired by this answer by @James to see how griddata and map_coordinates might be used. In the examples below I\'m showing 2D data, but my i

1条回答
  •  轮回少年
    2020-12-14 03:33

    Good question! (and nice plots!)

    For unstructured data, you'll want to switch back to functions meant for unstructured data. griddata is one option, but uses triangulation with linear interpolation in between. This leads to "hard" edges at triangle boundaries.

    Splines are radial basis functions. In scipy terms, you want scipy.interpolate.Rbf. I'd recommend using function="linear" or function="thin_plate" over cubic splines, but cubic is available as well. (Cubic splines will exacerbate problems with "overshooting" compared to linear or thin-plate splines.)

    One caveat is that this particular implementation of radial basis functions will always use all points in your dataset. This is the most accurate and smooth approach, but it scales poorly as the number of input observation points increases. There are several ways around this, but things will get more complex. I'll leave that for another question.

    At any rate, here's a simplified example. We'll generate random data and then interpolate it at points that are on a regular grid. (Note that the input is not on a regular grid, and the interpolated points don't need to be either.)

    import numpy as np
    import scipy.interpolate
    import matplotlib.pyplot as plt
    np.random.seed(1977)
    
    x, y, z = np.random.random((3, 10))
    
    interp = scipy.interpolate.Rbf(x, y, z, function='thin_plate')
    
    yi, xi = np.mgrid[0:1:100j, 0:1:100j]
    
    zi = interp(xi, yi)
    
    plt.plot(x, y, 'ko')
    plt.imshow(zi, extent=[0, 1, 1, 0], cmap='gist_earth')
    plt.colorbar()
    
    plt.show()
    


    Choice of spline type

    I chose "thin_plate" as the type of spline. Our input observations points range from 0 to 1 (they're created by np.random.random). Notice that our interpolated values go slightly above 1 and well below zero. This is "overshooting".


    Linear splines will completely avoid overshooting, but you'll wind up with "bullseye" patterns (nowhere near as severe as with IDW methods, though). For example, here's the exact same data interpolated with a linear radial basis function. Notice that our interpolated values never go above 1 or below 0:


    Higher order splines will make trends in the data more continuous but will overshoot more. The default "multiquadric" is fairly similar to a thin-plate spline, but will make things a bit more continuous and overshoot a bit worse:


    However, as you go to even higher order splines such as "cubic" (third order):

    and "quintic" (fifth order)

    You can really wind up with unreasonable results as soon as you move even slightly beyond your input data.


    At any rate, here's a simple example to compare different radial basis functions on random data:

    import numpy as np
    import scipy.interpolate
    import matplotlib.pyplot as plt
    np.random.seed(1977)
    
    x, y, z = np.random.random((3, 10))
    yi, xi = np.mgrid[0:1:100j, 0:1:100j]
    
    interp_types = ['multiquadric', 'inverse', 'gaussian', 'linear', 'cubic',
                    'quintic', 'thin_plate']
    
    for kind in interp_types:
        interp = scipy.interpolate.Rbf(x, y, z, function=kind)
        zi = interp(xi, yi)
    
        fig, ax = plt.subplots()
        ax.plot(x, y, 'ko')
        im = ax.imshow(zi, extent=[0, 1, 1, 0], cmap='gist_earth')
        fig.colorbar(im)
        ax.set(title=kind)
        fig.savefig(kind + '.png', dpi=80)
    
    plt.show()
    

    0 讨论(0)
提交回复
热议问题