Interpolation method that does not add unnecessary extremums

后端 未结 3 1656
梦毁少年i
梦毁少年i 2020-12-20 01:50

This question is half programming but also half mathematics. I want to interpolate a set of points by a curve without adding unnecessary extremums staying \"close to the lin

相关标签:
3条回答
  • 2020-12-20 02:30

    You can use the linear interpolation and then filter it (with a mean filter) :

    size = 51.0;    
    fun = interpolate.interp1d(xp, yp,kind='linear');
    filt = (1/size)*np.ones(size);
    yc = signal.convolve( fun(xc),filt,'same');
    

    With the parameter sizeyou can control the smoothing degree.

    enter image description here

    This is the integrated code:

    import numpy as np
    from scipy.interpolate import interp1d
    import matplotlib.pyplot as plt
    from scipy import interpolate,signal
    
    fig = plt.figure()
    ax = fig.add_subplot(1,1,1)
    ax.spines['left'].set_position('zero')
    ax.spines['right'].set_color('none')
    ax.spines['bottom'].set_position('zero')
    ax.spines['top'].set_color('none')
    ax.xaxis.set_ticks_position('bottom')
    ax.yaxis.set_ticks_position('left')
    
    list_points=[(-3,0.1),(-2,0.15),(0,4),(2,-6),(4,-2),(7,-0.15),(8,-0.1)]
    (xp,yp)=zip(*list_points)
    xc=np.linspace(min(xp),max(xp),300)
    
    ########################################################
    size = 41.0;#Put here any odd number
    fun = interpolate.interp1d(xp, yp,kind='linear');
    filt = (1/size)*np.ones(size);
    yc = signal.convolve(fun(xc),filt,'same');
    ########################################################
    
    plt.plot(xp,yp,'o',color='black',ms=5)
    plt.plot(xc,yc)
    plt.plot(xc,fun(xc))
    plt.show()
    
    0 讨论(0)
  • 2020-12-20 02:54

    While not exactly the same(?), your question is similar to this one, so perhaps the same answer would be useful. You can try a monotonic interpolator. The PchipInterpolator class (which you can refer to by its shorter alias pchip) in scipy.interpolate can be used. Here's a version of your script with a curve created using pchip included:

    import numpy as np
    from scipy.interpolate import interp1d, pchip
    import matplotlib.pyplot as plt
    
    fig = plt.figure()
    ax = fig.add_subplot(1,1,1)
    ax.spines['left'].set_position('zero')
    ax.spines['right'].set_color('none')
    ax.spines['bottom'].set_position('zero')
    ax.spines['top'].set_color('none')
    ax.xaxis.set_ticks_position('bottom')
    ax.yaxis.set_ticks_position('left')
    
    list_points = [(-3,0.1),(-2,0.15),(0,4),(2,-6),(4,-2),(7,-0.15),(8,-0.1)]
    (xp,yp) = zip(*list_points)
    fun = interp1d(xp,yp,kind='cubic')
    
    xc = np.linspace(min(xp),max(xp),300)
    
    plt.plot(xp,yp,'o',color='black',ms=5)
    plt.plot(xc,fun(xc))
    fun2 = interp1d(xp,yp,kind='linear')
    plt.plot(xc,fun2(xc))
    
    p = pchip(xp, yp)
    plt.plot(xc, p(xc), 'r', linewidth=3, alpha=0.6)
    
    plt.show()
    

    The plot it generates is shown below.

    • Black dots: Original data
    • Green lines: linear interpolation
    • Blue lines: cubic spline interpolation
    • Red lines: pchip interpolation

    plot

    0 讨论(0)
  • 2020-12-20 02:55

    Have you tried a quadratic spline instead - though I am not convinced that will help. Another fudge option is to add additional data-points very close to your maximums. e.g. at (-0.05,4) and (1.95, -6) - this would cause the cubic spline algorithm to flatten those areas near the maximum. Depends what you are trying to achieve. There are techniques to constrain maximum and minimum of cubic splines but I am not familiar enough with those or python / matplotlib to help, sorry!

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