abs() for Absolutes

Concepts covered: Math Ops

abs returns how far a number lies from zero: the same number with its sign removed. It accepts integers and floats and gives back the type it received.

print(abs(-7))
print(abs(7))
print(abs(-2.5))
print(abs(0))

Output:

7
7
2.5
0

The distance between 2 numbers

The everyday form is abs(a - b): how far apart 2 values are, whichever is larger. Subtraction alone returns a signed answer that flips with the order you wrote, and wrapping it in abs makes the order stop mattering. Here a running watch and a map disagree about a route's elevation gain.

watch_m = 482
map_m = 470

print(watch_m - map_m)
print(map_m - watch_m)
print(abs(map_m - watch_m))
print(abs(watch_m - map_m))

Output:

12
-12
12
12

Tolerance checks

Two measurements from different devices rarely agree exactly, so comparing them with == fails over a 1-metre disagreement. A useful check asks whether the gap is small enough: abs(a - b) <= tolerance.

TOLERANCE_M = 15

def elevation_ok(watch_m, map_m):
    return abs(watch_m - map_m) <= TOLERANCE_M

print(elevation_ok(482, 470))
print(elevation_ok(430, 470))
print(elevation_ok(500, 470))

Output:

True
False
False

Drop the abs and the second call returns True. The difference 430 - 470 is -40, and -40 is below every positive tolerance, so a watch reading 40 metres low would pass a check it should fail.

Which expression tells whether 2 readings, a and b, are within 5 of each other in either direction?

Signed difference or size?

Removing the sign removes information. Whether a runner got faster or slower than last week lives in the sign of this_week - last_week, and how big the change was lives in its absolute value. Keep the signed number when direction matters, and take abs when only size does.

A climb profile shows both at once. Five elevation readings give a net change from the first point to the last, and a total amount of climbing and descending along the way. Only the second needs abs.

elevation = (12, 30, 22, 41, 35)
moved = 0

for i in range(1, len(elevation)):
    step = elevation[i] - elevation[i - 1]
    moved = moved + abs(step)
    print(step, moved)

net = elevation[-1] - elevation[0]
print("net:", net, "moved:", moved)
18 18
-8 26
19 45
-6 51
net: 23 moved: 51

The net change is 23 metres, yet the runner moved 51 metres up and down. Adding the signed steps would cancel each descent against a climb and land on 23 again, hiding 28 metres of effort.

Average size of an error

The same idea measures how wrong a forecast was. A pace predictor guessed each kilometre before the run; the mean absolute error averages the size of each miss, so misses in opposite directions cannot cancel.

predicted = (300, 295, 300, 290, 285)
actual = (312, 298, 305, 291, 284)

total_miss = 0
for i in range(len(actual)):
    total_miss = total_miss + abs(actual[i] - predicted[i])

print(total_miss)
print(total_miss / len(actual))

Output:

22
4.4

Summing the signed misses gives 20 instead of 22, because the last kilometre ran 1 second faster than predicted and that -1 cancels part of the others. With larger misses in both directions, a signed average can sit near 0 while every prediction is far off.

Common mistakes

abs(a) - abs(b) and abs(a - b) are different calculations. With a = -3 and b = 4, the first is 3 - 4, which is -1; the second is abs(-7), which is 7. Only the second is a distance.

abs takes 1 number. A list of gaps needs a loop that calls abs on each item. Passing the list itself, as in abs(gaps), stops the program with TypeError: bad operand type for abs(): 'list', and a number stored as text such as "-12" fails the same way, with 'str' at the end of the message.

gaps = [12, -40, 30]
print(abs(gaps[1]))

for g in gaps:
    print(abs(g))

Output:

40
12
40
30

About this lesson

This section is part of the Collections: Beginner lesson on DataDriven, the home of data engineering. Lessons cover SQL, Python, Spark, data modeling and pipeline architecture, and each section pairs its explanation with worked examples and practice you run as you go.