I have a function f(x) which gives f(x)=0 for two to three values of x. I want to find all the values of x for which f(x)=0 but np.interp(0, f(x), x)
gives me the last value of x for which f(x)=0. How to get all the values?
I want to find the critical points of a function. I tried np.gradient(f(x))
and then interpolated it with np.interpolate(0, np.gradient(f(x)), x)
.
I have a function f(x) which gives f(x)=0 for two to three values of x. I want to find all the values of x for which f(x)=0 but np.interp(0, f(x), x)
gives me the last value of x for which f(x)=0. How to get all the values?
I want to find the critical points of a function. I tried np.gradient(f(x))
and then interpolated it with np.interpolate(0, np.gradient(f(x)), x)
.
1 Answer
Reset to default 2That's not what np.interp()
does. From the docs: One-dimensional linear interpolation for monotonically increasing sample points. You are basically resampling, or in your case, interpolating the value of f(x) at x=0.
You seem to be giving (0,f,x) as arguments possibly(?) trying to swap xp,fp, in general this won't work. If you have exact zeros in your dataset, just use idx=np.where(f==0.0)
and return the x values as shown below.
If your goal is to get the values where any function is 0, then things get kinda trickier. In a discrete case, your best bet in finding a 0 is to think of it as an intersection with the x-axis, meaning a change of sign for f (Bolzano's Theorem). Check this post for the sign change.
The next problem is that, while simply using np.sign()
(like in the link above) will almost always work, for f=[1,0,-1]
it will detect 2 changes of sign! One from 1 to 0 and one from 0 to -1. So we go with the solution of gathering all signs >=0, creating a boolean mask, and then with np.diff()
acting on that, we should get changes of sign without 0 being counted twice.
You can try this:
import numpy as np
num = 10
x = np.linspace(0,4*np.pi,num)
f = np.sin(x)
def get_zero_crossings(f,x):
# identify indices where adjacent element signs are opposite
# this will return the left element
idx = np.where(np.diff(np.sign(f)>=0))[0]
# line equation, honestly there is probably a better way to do this
x_zeros = x[idx] - f[idx] * (x[idx + 1] - x[idx]) / (f[idx + 1] - f[idx])
return x_zeros
print(get_zero_crossings(f,x))
Simply get your np.gradient(f), x
through the above function, and you should probably get the critical points of f.
f(x)
look like? – jared Commented Mar 31 at 3:29xp
argument should be 'monotonically increasing'. This isn't enforced, butif the sequence xp is non-increasing, interpolation results are meaningless.
– hpaulj Commented Mar 31 at 17:04