I have the given sample data and interpolated spline:
JavaScript
x
16
16
1
import matplotlib.pyplot as plt
2
import numpy as np
3
from scipy import interpolate
4
5
x = [0.1, 1.5, 2.3, 5.5, 6.7, 7]
6
y = [5, 4, 5, 2, 2, 3]
7
s = interpolate.UnivariateSpline(x, y, s=0)
8
9
xs = np.linspace(min(x), max(x), 10000) #values for x axis
10
ys = s(xs)
11
12
plt.figure()
13
plt.plot(xs, ys, label='spline')
14
plt.plot(x, y, 'x', label='collected data')
15
plt.legend()
16
I would like to pull the x values that correspond to the integer y values of the spline, but am not sure how to do this. I assume I will be using np.where() and have tried (to no avail):
JavaScript
1
2
1
root_index = np.where(ys == ys.round())
2
Advertisement
Answer
You could use the find_roots
function from this post to find the exact interpolated x-values:
JavaScript
1
28
28
1
import matplotlib.pyplot as plt
2
import numpy as np
3
from scipy import interpolate
4
5
def find_roots(x, y):
6
s = np.abs(np.diff(np.sign(y))).astype(bool)
7
return x[:-1][s] + np.diff(x)[s] / (np.abs(y[1:][s] / y[:-1][s]) + 1)
8
9
x = [0.1, 1.5, 2.3, 5.5, 6.7, 7]
10
y = [5, 4, 5, 2, 2, 3]
11
s = interpolate.UnivariateSpline(x, y, s=0)
12
13
xs = np.linspace(min(x), max(x), 500) # values for x axis
14
ys = s(xs)
15
16
plt.figure()
17
plt.plot(xs, ys, label='spline')
18
19
for y0 in range(0, 7):
20
r = find_roots(xs, ys - y0)
21
if len(r) > 0:
22
plt.scatter(r, np.repeat(y0, len(r)), label=f'y0 = {y0}')
23
for ri in r:
24
plt.text(ri, y0, f' {ri:.3f}', ha='left', va='center')
25
plt.legend()
26
plt.xlim(min(x) - 0.2, max(x) + 1)
27
plt.show()
28
PS: with much less points for the x’s, e.g. xs = np.linspace(min(x), max(x), 50)
, the curve would look a bit bumpy, and the interpolation would be slightly different: