I'm using the interp1d
function for interpolation
from scipy.interpolate import interp1d
x = [0, 3, 6, 10, 15, 20]
y = [1.87, 1.76, 1.27, 1.185, 0.995, 0.855]
f = interp1d(x, y, bounds_error=False)
x_find = [0, 5, 8, 10, 28]
print(f(x_find))
Using bounds_error=False
in f = interp1d(x, y, bounds_error=False)
returns nan value for x=28 in x_find
.
Since interp1d raises an error for single datapoints, I tried the following for single datapoint.
x0 = [1.87]
y0 = [0.93]
f0 = lambda x: y0[0] if np.isclose(x, x0[0]) else np.NaN
print(f0(x0[0]))
This doesn't work when I try f0(x_find)
.
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Expected output:
f0(x_find)
returns nan for values of x in x_find not present in x0
like how bounds_error
works.
Suggestions on how to do this will be really helpful
EDIT:
Question:
Would it be possible to modify the interpolation function of the single datapoint so that we could do just f(x_find), something similar to the one returned by f = interp1d() ?
CodePudding user response:
I just only guess that you are missing a very simple thing: to put a single value to the f0()
function using a list comprehension to get all values in case of a list with values.
Does the following code:
import numpy as np
from scipy.interpolate import interp1d
x = [0, 3, 6, 10, 15, 20]
y = [1.87, 1.76, 1.27, 1.185, 0.995, 0.855]
f = interp1d(x, y, bounds_error=False)
x_find = [0, 5, 8, 10, 28]
print(f(x_find))
x0 = [1.87]
y0 = [0.93]
f0 = lambda x: y0[0] if np.isclose(x, x0[0]) else np.NaN
print(f0(x0[0]))
print([f0(x) for x in x_find])
which prints:
[1.87 1.43333333 1.2275 1.185 nan]
0.93
[nan, nan, nan, nan, nan]
meet your expectations?
You can also redefine f0 to cover the case of passing a list of values to it as follows:
def f0(x):
import numpy as np
x0 = [1.87]
y0 = [0.93]
f = lambda x: y0[0] if np.isclose(x, x0[0]) else np.NaN
if isinstance(x, list):
return [f(z) for z in x]
elif isinstance(x, float):
return f(x)
else:
return "f0() accepts only float and lists of floats as parameter"
print('---')
print(f0(1.87))
print(f0(x_find))
print(f0("5"))
The output of the code above is:
---
0.93
[nan, nan, nan, nan, nan]
f0() accepts only float and lists of floats as parameter
FINALLY you can also redefine f0 as f_i which is a bit complex code simulating the behavior of scipy interp1d as follows:
def f_i(X=[1.87], Y=[0.93], bounds_error=False):
# ToDo: implementation of bounds_error evaluation
import numpy as np
def f(v):
for i, x in enumerate(X):
if np.isclose(v, x):
return Y[i]
else:
return np.NaN
def r_f(w):
if isinstance(w, list):
return [f(z) for z in w]
elif isinstance(w, float):
return f(w)
else:
return "ValueErrorMessage: param. not float or list of floats"
return r_f
y = [1.87, 1.76, 1.27, 1.185, 0.995, 0.855]
x = [ 0, 3, 6, 10, 15, 20 ]
print('---')
f = f_i()
print(f(1.87))
f = f_i(x, y)
x_find = [0, 5, 8, 10, 28]
print(f(x_find))
print(f("5"))
which gives following output:
---
0.93
[1.87, nan, nan, 1.185, nan]
ValueErrorMessage: param. not float or list of floats