15. Median Math Confusion


#1

Hi all,

I have FINALLY finished this section of the course, but I can't say that I understand the math of the code I wrote. It works, and most of it makes sense, but I am hung up on how the whole thing works together. Here is my code:

def median(numbers):
    gah = sorted(numbers)
    n = len(gah)
    m = n-1
    print gah[n//2]
    print gah[m//2]
    return (gah[n//2] + gah[m//2]) / 2.0

print median([7, 12, 3, 1, 6])

Based on the list I'm calling, the len(gah) should be 5. That makes sense.

Once the numbers are sorted to [1,3,6,7,12], the indices make sense, but I lose the math. For gah[n//2], we are returning a specific index of the list. If n = 5, and we've divided that by 2, the answer should be 6, as that is the number at index 2. And it is! When I take the same n = 5 and subtract 1, I get m = 4. If I divide that by 2, I will also get 2, and that will also tag 6 for gah[2].

My question is, how does this math end up providing the mean...? Why do we need to subtract 1 from the length for the second number?? Is this just confusing me because my list is odd, and it would make more sense with an even list? The subtraction of 1 from the length does not make any sense to me. Sigh. :neutral_face:


#2

In a list of odd-numbered length there is a middle entry. In your example that is 6. This middle entry is the median(if the list is sorted).

But in a list with an even number there is no middle entry, because the middle "is between" two numbers. To get the median here you take both those numbers and compute their average. For example

[1, 3, 4, 7]

The middle is between the entries 3 and 4 so you take the average of 3 and 4.

(3 + 4) / 2.0 = 3.5

In your example this doesn't really make a difference because you have an actual middle number that you double and then halve to get back to the original number.


#3

Ok, but why are we subtracting 1 from the length of the list? This is the part I don't understand.


#4

Ah, that would be a mistake :smiley: I'd take the element at len/2 and at (len/2)-1. Seems like a mistake.


#5

I don't think there is a mistake here
@tsluyter 's method will yield the same indices as yours.

Keep in mind that a list with e.g. 10 elements has no element at index 10, because the numbering starts at 0.

Here is an example for a list with an even number of elements:

my_list =[1, 2, 3, 4, 5, 6]
# ind     0  1  2  3  4  5

Below every element I wrote it's index. len(my_list) is 6. Divided by 2 this gives us 3, which is the index of the element above the middle. (6-1)//2 gives us 2, because the // operator rounds the value of the division to the next lower whole number. This is the index below the middle.

If the list has an odd number of elements length / 2 and (length -1) / 2 yield the same result.
Any number that is odd can be written in the form 2n + 1 where n is a whole number greater or equal to 0.
For example 9 = 2*4 + 1
Now when the length of the list floor divided by two is (2n + 1) // 2 = floor(n + 0.5) = n
and the length minus one floor divided by 2 is (2n + 1 - 1) // 2 = 2n // 2 = n.
So in the odd case both indices are the same.


#6

I too was having issues with understanding the math of it, so I spent some time nawing over it and this is what I came up with.

def median(nums):

num = sorted(nums)
'''This sorts the numbers in the original list (nums), from lowest to highest, and creates a new list (num).
From here everything is done with the new list only, leaving the original list alone'''

length = len(num)
'''This assigns the length of the new string (num) to the variable length. It determines or answers the question:
How many numbers are in the list?___ Then assigns it to a variable. length of the list (len) counts exclusively
ie: 1, 2, 3, 4, 5,...'''

index = length - 1
'''The variable index is equal to the length of the index for the list (num), minus 1,
the minus 1 is referring to the lists index and indicates that it should
go backwards one index number through the list. index counts inclusively ie: 0, 1, 2, 3, 4, 5,...'''

'''So in order for index to be equal to length it has to be deducted by 1
nums = [12, 24, 36, 2, 7, 8, 5, 48]
length=1, 2, 3, 4,  5,  6,  7,  8,
num = [2, 5, 7, 8, 12, 24, 36, 48]
index= 0, 1, 2, 3,  4,  5,  6,  7, 8

length = 8
index = 7
what it would look like in normal human math: ((8/2) + (7/2)) / 2 = ?
'''

'''This line is asking to return to us: (using this list(num) get the ( length of the list(length) (/)divided by 2 )
(+)then add it to, using this list(num) (get the length of the index minus 1 (index) (/)divided by 2 )) (/)divided by 2'''
return (num[length//2] + num[index//2]) / 2.0

This helped me understand it better, so I thought I'd share it with you. Hope it helps you too.


#7

Thank you so much for this! This has been driving me crazy but I understand it now :smile: