Dataframe format:
tooth_id | x_center | y_center | width | height | quadrant |
---|---|---|---|---|---|
1 | 0.309643 | 0.082520 | 0.072325 | 0.169476 | |
2 | -0.211200 | -0.057675 | 0.071321 | 0.199645 | |
3 | -0.307634 | -0.127773 | 0.081366 | 0.187223 | |
4 | -0.262933 | -0.093611 | 0.065294 | 0.211180 | |
5 | 0.253139 | 0.136646 | 0.096936 | 0.190772 |
Question: how to write a loop to deliver the following outcome? In each roll:
if x_center >=0 and y_center >= 0, quadrant = 1
if x_center <0 and y_center >= 0, quadrant = 2
if x_center <0 and y_center <0, quadrant = 3
if x_center >0 and y_center <0, quadrant = 4
Here's another solution, using arctan2
and a little modular arithmetic. Note that Corralien's approach is much more generalizable. What follows is very specific to this use-case.
import numpy as np
deg = np.round(180 * np.arctan2(df.y_center, df.x_center) / np.pi).astype(int)
df["quadrant"] = 1 + ((deg + 360) % 360) // 90
Output:
>>> df
tooth_id x_center y_center width height quadrant
0 1 0.309643 0.082520 0.072325 0.169476 1
1 2 -0.211200 -0.057675 0.071321 0.199645 3
2 3 -0.307634 -0.127773 0.081366 0.187223 3
3 4 -0.262933 -0.093611 0.065294 0.211180 3
4 5 0.253139 0.136646 0.096936 0.190772 1
Note, points on the axes are "rolled over" into the neighboring quadrant in the anti-clockwise direction, e.g., the point (0, 0.631)
, which lies at 90° is considered quadrant 2; (-0.578, 0)
, which lies at 180° is considered quadrant 3, etc.
Use np.arctan2()
to get the angle (in degrees) formed by each (x, y)
point:
>>> deg = np.round(180 * np.arctan2(df.y_center, df.x_center) / np.pi).astype(int)
>>> deg
0 15
1 -165
2 -157
3 -160
4 28
dtype: int32
Now, convert (-180°, 180°]
to [0°, 360°)
:
>>> deg = (deg + 360) % 360
>>> deg
0 15
1 195
2 203
3 200
4 28
dtype: int32
Floor divide by 90 to get the quadrant (which'll return 0, 1, 2, 3 -- so also add 1):
>>> quadrant = 1 + (deg // 90)
>>> quadrant
0 1
1 3
2 3
3 3
4 1
dtype: int32