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
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.