I'm getting ValueError: math domain error
for some points in dataframe. I know acos takes value from -1 to 1.
I tried solving the error using decimal.Decimal function. But it is still throwing the error for the same points.
def angle(p1,p2,p3):
dot_product = np.dot(p2-p1,p3-p2)
vec1 = np.linalg.norm(p2-p1)
vec2 = np.linalg.norm(p3-p2)
x = dot_product /(vec1 * vec2)
return round(math.degrees(math.acos(x)),2)
def get_angle(points):
return [[angle(point1[0], point1[1], point2[1]) for point2 in points.values] for point1 in points.values]
# this is the column on which i'm apply the function
# this is one of the sample group
# I have to find angle between the co-ordinates
# function return a list of angles w.r.t other points
points
[[-140.78063986473717, 91.91634474415332], [-142.34375254437327, 87.6819673711434]]
[[-141.25677946582437, 94.60493099503219], [-142.7676919612568, 90.44367777556181]]
[[-138.125714250491, 86.75676850322634], [-139.46260946977418, 82.95679492782801]]
[[-137.67089835880324, 74.81029774621129], [-139.08569156355225, 70.57744785398245]]
For example,
p1 = np.array([-138.125714250491, 86.75676850322634])
p2 = np.array([-139.46260946977418, 82.95679492782801])
p3 = np.array([-132.35878855874762, 95.67247487790883])
math.degrees(math.acos(np.dot(p2-p1,p3-p2)/(np.linalg.norm(p2-p1) * np.linalg.norm(p3-p2))))
>>> 170.19212016382508
adding x = Decimal(dot_product /(vec1 * vec2))
does not solve the problem
I think the culprit is multiplication and division operation, which is leaving the results above 1 and below -1 for some points in the dataframe. How to solve this problem?
CodePudding user response:
If the values of x
are out of the interval [-1, 1] by just a tiny amount--as the result of normal floating point imprecision--you could clip the values to the interval before passing them to acos
. Something like acos(max(min(x, 1), -1))
should work.