Creating an incremental smooth spline curve instead of non-uniform increments in python

Question:

I am trying to smoothen my data using spline – which is basically cumulative percentile on the y-axis and a reference point they refer to on the x-axis. I get most part of it correct, however, the challenge I am facing is my y axis is increasing in a non linear way – as seen int he spline plot below- y-axis value keep increasing and decreasing, instead of just increasing.

I still want a smooth curve but want y-axis to increase with the x-axis – i.e. each subsequent y-axis point should be equal or a slight increment in value from the previous value, as opposed to increasing and the decreasing later.

Reproducible code:

import pandas as pd 
import numpy as np 
from scipy.interpolate import make_interp_spline 
import matplotlib.pyplot as plt 
from matplotlib.pyplot import figure 

percentile_block_df = pd.DataFrame({ 
'x' : [0.5,100.5,200.5,400.5,800.5,900.5,1000.5], 
'percentile' : [0.0001,0.01,0.065,0.85,0.99,0.9973,0.9999] 
})

figure(figsize=(8, 6), dpi=80) 
y = percentile_block_df.percentile 
x = percentile_block_df.x 

X_Y_Spline = make_interp_spline(x, y) 

# Returns evenly spaced numbers 
# over a specified interval. 
X_ = np.linspace(x.min(), x.max(), 1000)
Y_ = X_Y_Spline(X_)

figure(figsize=(18, 6), dpi=80)
plt.subplot(1, 2, 1) # row 1, col 2 index 1
plt.plot(x, y,"ro")
plt.plot(x, y)
plt.title("Original")
plt.xlabel('X')
plt.ylabel('Percentile ')

plt.subplot(1, 2, 2) # index 2
plt.plot(x, y,"ro")
plt.plot(X_, Y_,"green")
plt.title("Spline Plot")
plt.xlabel('X')
plt.ylabel('Percentile ')

plt.show()

See Chart

Asked By: user3562074

||

Answers:

What you are looking for is "monotonicity preserving interpolation". A quick search shows that scipy.interpolate.PchipInterpolator does just that. Here is the result for your example when simply plugging in from scipy.interpolate import PchipInterpolator instead of from scipy.interpolate import make_interp_spline.

enter image description here

Whether or not that’s appropriate depends of course on your specific requirements for the interpolation. I encourage you to research the other options which are out there.

Similar question:

Answered By: mcsoini

Code that eventually worked for me:

This link, explains the need for Monotone cubic interpolation

#this code allows "smoothening" of the data
B_spline_coeff1 = PchipInterpolator(x1, np.log(y1))
X1_Final = np.linspace(x.min(), x.max(), 1000)
Y1_Final = np.exp(B_spline_coeff1(X1_Final))

#plot subplots
figure(figsize=(18, 6), dpi=80)
plt.subplot(1, 2, 1) # row 1, col 2 index 1
plt.plot(x, y,"ro")
plt.plot(x, y)
plt.title("Original")
plt.xlabel('X')
plt.ylabel('Percentile ')

plt.subplot(1, 2, 2) # index 2
plt.plot(x, y,"ro")
plt.plot(X1_Final, Y1_Final,"green")
plt.title("Spline Plot")
plt.xlabel('X')
plt.ylabel('Percentile ')

plt.show()
Answered By: user3562074
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.