Reputation: 1349
For the following curve with non-equidistant x values, I would like to have smoothed y values.
How can this be done in Python?
import numpy as np
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
import pandas as pd
x = [0,0.1, 0.3, 0.6,0.7, 0.8, 0.9, 1.2, 1.4, 1.6, 1.9, 2.1, 2.4, 2.6, 2.9, 3.1, 3.3, 3.6, 4.0, 4.1, 4.5, 4.7, 5.1, 5.6, 5.9, 6.1]
y = np.sin(x) + np.random.random(len(x)) * 0.4
df = pd.DataFrame(y,index=x)
plt.plot(df, "-o", markersize=2)
plt.grid()
plt.show()
Upvotes: 0
Views: 457
Reputation: 2600
There are many things you could do to 'smooth' your curve. One effective way is to look at the scipy.interpolate library and use the UnivariateSpline function:
from scipy.interpolate import UnivariateSpline
x = np.array([0,0.1, 0.3, 0.6,0.7, 0.8, 0.9, 1.2, 1.4, 1.6, 1.9, 2.1, 2.4,
2.6, 2.9, 3.1, 3.3, 3.6, 4.0, 4.1, 4.5, 4.7, 5.1, 5.6, 5.9, 6.1])
y = np.sin(x) + np.random.random(len(x)) * 0.4
plt.plot(x, y, "-o", markersize=2)
s = UnivariateSpline(x,y)
x_interp = np.linspace(0, 6, 1000)
plt.plot(x_interp, s(x_interp), 'r-')
plt.xlabel('x')
plt.ylabel('y')
What does UnivariateSpline do?
I'm no expert but essentially you are fitting piecewise polynomials (of specified degree, here I used the default parameters) between different points (or knots) in x
. The freedom of the interpolation increases as the number of knots or degree of the polynomial increases. Essentially you are minimising the error in the interpolated data, but don't want to over describe the data.
That being said, if you know the expected form of your signal, you would be much better fitting a sine curve to the data...
Upvotes: 2