Search code examples
pythonscipyjupyterinterpolation

Interpolating a curve on a plot


I am hoping to plot a smooth curve given a number of points (1-d x and y array). I thought I could use the package make_interp_spline but it looks like the x array needs to be sorted evenly... How do I use make_interp_spline without sorting the x dimension of the array or work around the error?

from scipy.interpolate import make_interp_spline
import numpy as np
#from scipy import stats
import matplotlib.pyplot as plt


x = np.array([-31,-30,-30,-32,-36,-39])
y = np.array([60,62,64,65,64,64])

#plot non-interpolated curve 
plt.plot(x,y);

#x = x.reshape(6)
#y = y.reshape(6)

# wher the error occurs about the 1d sorted array
X_Y_Spline = make_interp_spline(x, y)

X_ = np.linspace(x.min(), x.max(), 500)
Y_ = X_Y_Spline(X_)

plt.plot(X_, Y_);


---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
/tmp/ipykernel_2083810/662623888.py in <module>
      7 #y = y.reshape(6)
      8 
----> 9 X_Y_Spline = make_interp_spline(x, y)
     10 
     11 X_ = np.linspace(x.min(), x.max(), 500)

~/miniconda3/envs/py3_std_maps/lib/python3.9/site-packages/scipy/interpolate/_bsplines.py in make_interp_spline(x, y, k, t, bc_type, axis, check_finite)
    784 
    785     if x.ndim != 1 or np.any(x[1:] < x[:-1]):
--> 786         raise ValueError("Expect x to be a 1-D sorted array_like.")
    787     if np.any(x[1:] == x[:-1]):
    788         raise ValueError("Expect x to not have duplicates")

ValueError: Expect x to be a 1-D sorted array_like.

Solution

  • Workaround is to make a monotonically increasing n dimension where x and y arrays can follow.

    See:

    from scipy.interpolate import interp1d
    import numpy as np
    import matplotlib.pyplot as plt
    
    
    x = np.array([-31,-30,-30,-32,-36,-39])
    n = np.arange(x.shape[0]) 
    y = np.array([60,62,64,65,64,64])
    
    
    x_spline = interp1d(n, x,kind='cubic')
    
    n_ = np.linspace(n.min(), n.max(), 500)
    y_spline = interp1d(n, y,kind='cubic')
    
    x_ = x_spline(n_)
    y_ = y_spline(n_)
    
    
    
    plt.plot(x_, y_)
    
    plt.plot(x,y);
    

    enter image description here