Search code examples
pythonpandasfor-loopwhere-clause

How to determine quadrant given x- and y-coordinate columns in Pandas DataFrame


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  

Solution

  • Solution

    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.

    Steps

    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