Calculate the movement required to get from one angle to another angle on a compass The goal of the function is to find out how to get from one angle to another angle. Two things are involved: the amount to move by and the direction (+ means turn right, - means turn left). The most the angle will have to move by is 180deg. The function is rather short. I wanted to avoid using and trig functions or pi. I want this as fast as I can while maintaining readability.

import pandas as pd
import numpy as np

def get_wind_dir_difd(dir_1, dir_2):
    """
    Figures out the shortest way to get from dir_1 to dir_2. Positive nunber go clockwise, negative numbers go counter clockwise.
    NOTE: The direction 0 and 360 are the same.
    :param dir_1: int. The direction of the first wind.
    :param dir_2: The direction of the second wind.
    :return: int. The what to add (can be a negative number too) to the first wind dir to get to the second wind dir.
    """
    diff = dir_2 - dir_1

    if diff &gt; 180:  # the highest diff can be is 180
        diff = 360 - diff

    elif diff &lt; -180:  # the lowest diff can be is -180
        diff = 360 + diff

    if dir_2 &gt; dir_1 and (dir_2 - dir_1 &gt; 180):  # ensures the correct sign is used when dir_2 is larger and the difference betwene the two is more than 180, EX 10, 310 or 40, 360
        diff = -diff

    return diff

# IGNORE WHAT IS BELOW, THAT IS JUST TO TEST

get_wind_dir_dif_vec = np.vectorize(get_wind_dir_difd)

df = pd.read_csv('test.csv')

df['diff'] = get_wind_dir_dif_vec(df['val1'], df['val2'])

for i in range(len(df)):
    row = df.iloc[i]
    correct_or_not = row['diff'] == row['what_diff_should_be']
    if correct_or_not:
        correct_or_not = ''
    else:
        correct_or_not = 'X'
    df.set_value(i, ' bad_answer ', correct_or_not)

print(df)




To give you a better idea of the program

    val1  val2  diff  what_diff_should_be  bad_answer 
0    120    30   -90                  -90             
1    340    20    40                   40             
2     20   340   -40                  -40             
3    310    10    60                   60             
4     10   310   -60                  -60             
5      0   300   -60                  -60             
6    300     0    60                   60             
7    190   180   -10                  -10             
8    180   190    10                   10             
9    200   220    20                   20             
10   220   200   -20                  -20             
11    10   190   180                  180             
12   360     0     0                    0             
13     0   360     0                    0             
14   340    20    40                   40             
15   350     0    10                   10             
16   350   360    10                   10             
17    40   360   -40                  -40             
18   180     0  -180                 -180             
19     0   180   180                  180             




This is the csv I tested it on.

val1,val2,diff,what_diff_should_be
120,30,,-90
340,20,,40
20,340,,-40
310,10,,60
10,310,,-60
0,300,,-60
300,0,,60
190,180,,-10
180,190,,10
200,220,,20
220,200,,-20
10,190,,180
360,0,,0
0,360,,0
340,20,,40
350,0,,10
350,360,,10
40,360,,-40
180,0,,-180
0,180,,180
The other reviews give some good formatting advice so I'll concentrate solely on the function itself.  I would probably write this instead:

def dir_diff(dir1, dir2):
    diff = (dir2 - dir1) % 360
    return diff if diff &lt;= 180 else diff - 360


The way Python's % operator works, it assures that we always have a positive number from 0 to 360 for diff in the first line.  Then we only need to adjust if the value is greater than 180.  Note also that unlike all of the other versions (including the original), this version will also continue to work properly even if we pass in values such as 900, -92 or 725, 9900.

Better yet, use AJNeufeld's comment or twalberg's equivalent:

return 180 - (dir1 - dir2 + 180) % 360


In another comment, the OP said:


  Later I will use this function to interpolate missing data. So, if dir_1 is lower than dir_2 like it is with (0, 180) then the answer should be positive because 90 (90 b/c +180/2) would be the middle value and not -90. Hope that helps.


This requirement doesn't make sense to me because interpolation between two diametrically opposite points on a circle can legitimately be interpreted as either midpoint.  However, if it's really a requirement, we can combine like so:

def Edward2(dir1, dir2):
    diff = (dir2 - dir1 + 180) % 360 - 180
    return -diff if diff == -180 and dir1 &lt; dir2 else diff


If anyone cares, here is the test code I used:

import csv

def orig(dir_1, dir_2):
    diff = dir_2 - dir_1

    if diff &gt; 180:
        diff = 360 - diff

    elif diff &lt; -180:
        diff = 360 + diff

    if dir_2 &gt; dir_1 and (dir_2 - dir_1 &gt; 180):
        diff = -diff

    return diff

def Edward1(dir1, dir2):
    diff = (dir2 - dir1) % 360
    return diff if diff &lt;= 180 else diff - 360

def twalberg(dir1, dir2):
    return 180 - (dir1 - dir2 + 180) % 360

def AJneufeld(dir1, dir2):
    return (dir2 - dir1 + 180) % 360 - 180

def Edward2(dir1, dir2):
    diff = (dir2 - dir1 + 180) % 360 - 180
    return -diff if diff == -180 and dir1 &lt; dir2 else diff

if __name__=="__main__":
    green = "\x1b[32m"
    red = "\x1b[91m"
    white = "\x1b[37m"
    algo = [orig, Edward1, twalberg, AJneufeld, Edward2]


    def testAll(d1, d2, desired):
        print('{:-6} {:-6} {:-6}'.format(d1, d2, desired), end='')
        for fn in algo:
            calc = fn(int(d1),int(d2))
            color = [green, red][calc != desired]
            print('{}{:&gt;10}{}'.format(color, calc, white), end='')
        print()

    print('  dir1   dir2 desired', end='')
    for fn in algo:
        print(f'{fn.__name__:&gt;10}', end='')
    print()
    with open('input.csv') as csvfile:
        rowreader = csv.reader(csvfile)
        for row in rowreader:
            testAll(int(row[0]), int(row[1]), int(row[2]))


Here is the test data I used, with the format dir1,dir2,desired.

input.csv

120,30,-90
340,20,40
20,340,-40
310,10,60
10,310,-60
0,300,-60
300,0,60
190,180,-10
180,190,10
200,220,20
220,200,-20
10,190,180
360,0,0
0,360,0
340,20,40
350,0,10
350,360,10
40,360,-40
180,0,-180
0,180,180
1,181,180
359,179,-180
180,0,-180
181,1,-180
179,359,180
90,270,180
270,90,-180
-90,-270,-180
-270,-90,180
0,360,0
360,0,0
180,-180,0
-180,-180,0
-180,180,0
180,180,0
900,-92,88
725,9900,175
725,9905,180
9905,725,-180


Results

With the test cases shown, only the Edward2 function gets all results correct. I'm using Python 3.7.5.