Why is my median incorrect?

Question

Why is my median incorrect?

Answer

Finding the median of a list of numbers can be especially difficult if it’s an even number of numbers. To ensure that you’re actually working with the values you think you are, it can be very helpful to print them all out at each step. For example, when you sort your list, print your_sorted_list to see if it worked. When you calculate the midpoint, print your_midpoint to see if it’s the value at the middle index, or if it’s the middle index.
Half the battle is knowing what you’re working with at each step of the way. There are so many approaches to this particular problem that it’s not very meaningful to try and guess what could be wrong in your particular implementation. However, it will always be helpful to print your code out in steps, as that’s a major part of debugging!
Once you know what your values actually store, then you can proceed to make necessary changes with everything we’ve learned so far.

2 Likes

Because the interface’s answer is wrong. The solution prints the median where 4 and 5 are in the middle, in which the answer is 4.5. However, the interface inputs 5 and 5 in the middle, but still thinks the answer is 4.5, even though it would just be 5 (5 + 5 = 10 / 2 = 5).

The answer is 4.5 because they say to sort the list. This changes [4, 5, 5, 4] to [4, 4, 5, 5].

3 Likes

13 posts were split to a new topic: Why is my median incorrect?

Hello - I’ve been working on this problem for a while and I get an error that says my median function returns none. Specifically: “median([1]) returned None, did you remember to return the result?”

I can’t figure out why because I definitely am returning. Could someone please take a look and offer some advice?

Thank you.

def median(lst):
  lst = [] 
  sortedlst = sorted(lst) #sort input list of numbers
  middle = len(sortedlst) / 2 #find middle position of sorted list
  if len(sortedlst) == 1: #in the case that there's only one number
    return lst
  elif len(sortedlst) > 1 and len(sortedlst) % 2 == 0: #if more than one & even amount of numbers
    avg = float(sortedlst[middle] + sortedlst[middle+1] / 2)
    return avg
  elif len(sortedlst) > 1 and len(sortedlst) % 2 != 0: #if odd amount of numbers
    roundmid = round(middle) #would have to round the middle position if odd amount
    return sortedlst[roundmid]

print median([1,1,2]) #returns none???

you understand how function parameters (lst in your code) and arguments ([1, 1, 2] in your code) work? Because you overwrote the parameter with an empty list.

1 Like

Thanks! Had to go back and review the lists chapter for sure!

Actually I’ve been tinkering around with this and running into a different issue. Below is a sample code I tested in Python IDLE.

I now get an error in Codecademy that says “median([4, 5, 5, 4]) returned 4.0 instead of 4.5”

But IDLE returns test2 as 4.5. I suspect this has something to do with the floor division differences in versions 2 and 3, although I can’t seem to pinpoint where exactly I should change it so that Codecademy accepts my code. Any suggestions or recommendations?

def median(lst):
  sortedlst = sorted(lst) #sort input list of numbers
  middle = len(sortedlst) // 2 #find middle position of sorted list
  if len(sortedlst) == 1: #in the case that there's only one number
    return sortedlst[0]
  elif len(sortedlst) > 1 and len(sortedlst) % 2 == 0: #if more than one & even amount of numbers
    avg = (sortedlst[middle] + sortedlst[middle-1]) / 2
    return float(avg)
  elif len(sortedlst) > 1 and len(sortedlst) % 2 != 0: #if odd amount of numbers
    roundmid = round(middle) #would have to round the middle position if odd amount
    return sortedlst[roundmid]

test = [1, 45, 9, 91, 8, 8]

print (median(test))

test2 = [4, 5, 5, 4]
print (median(test2))

have you googled how the division behavior works in the different major python versions? You don’t use the division operator (/( a lot (only once in fact), so there is only line where the problem can be?

i didn’t count // because its floor division

1 Like

Hi All,

Just wanted to share my piece of code that is a very short version of the solution for this exercise:

def median(numbers):
  slist = sorted(numbers)
  nr = len(numbers)
  factor = 1 - nr % 2

  return (float(slist[ int(nr/2 - factor)]) + slist[int(nr/2)])/2

print median([4,5,5,4])

I hope you find this useful.

4 Likes
def median(nums):
  
  nums.sort()
  length = len(nums)
  halfNum = (length / 2) - 1
  if length == 1:
    answer1 = nums[0]
    
    return answer1
  
  elif length % 2 == 0:
    
    newNums = nums
    digit1 = newNums[halfNum]
    digit2 = nums[halfNum + 1]
    result = (digit1 + digit2) / 2.0
    
    return result
  else:
    oddanswer = nums[halfNum + 1]
    return oddanswer

This code works I just had to learn a few things, like len() returns a number not zero based answer, or I had to compensate for that.

halfNum = (length / 2) - 1
had to subtract 1 from the len() number to match the list[index]

Next was if I create a variable with variable = list.sort() I get (none type? item?) Whatever it was it always caused a error about (none type).

nums.sort() instead of x =nums.sort()
just putting this line in without making it a variable resulted in the list [nums] being permanently sorted, I did not realize that it changed it so i didnt have to make it a variable.

Things to keep in mind. This code is really novice and any constructive criticism is welcome.

2 Likes

The only problem with this is it modifies the middle element of an odd length list.

>>> print (median([7,4,5,3,5,4,6]))
5.0
>>> 

There is no 5.0 in that list. We should be returning the actual value, not a modified value.

That’s some pretty busy code for such a simple problem.

result = 0
def median(order):
mid = len(order) / 2 - 1
sort = sorted(order)
length = len(sort)
if length % 2 != 0:
return sort[mid]
else:
val1 = sort[mid]
val2 = sort[mid + 1]
global result
result = result + (val1 + val2) / 2.0
return result

print median([1])
print median([1, 2, 3])
print median([4, 5, 5, 4])
print median([1, 1, 2])
print median([3, 4, 9, 1])

I don’t know why this code doesn’t work. Can someone please help?

There are two possible solutions, depending upon the length of the sampe list. Can you solve one OR the other, then resolve this into something that can solve for both?

Could anyone advise why my code would be incorrect below?
I’m wondering why ‘-1’ is not included in the answer given by Codecademy.

def median(int_list):
  result = ''
  list_sorted = sorted(int_list)
  
  if len(int_list)%2 != 0:
  # if the length is odd
    result = list_sorted[(len(list_sorted)//2)-1]
    # Why don't I need '-1'?
    return result

  else:
  # if the length is even
    result = float((list_sorted[len(list_sorted)/2] + list_sorted[(len(list_sorted)/2)-1])/2.0)
    return result

why would you need -1?

If a list has a length of 3, the indexes/indices are: 0, 1, 2.
3 // 2 = 1
1 is the middle index. Subtracting one will now result in the wrong index, thus the wrong value.

for each list with odd/uneven length, you can apply this logic (you can try the math yourself for a list with a length of 5, 7, 9 and so forth)

Hi,

I just wanted to know if there was a better way I could have approached this problem. It seems very bloated with trying to get the middle indices. My code below works, just wondering if there is something I could have done differently.

def median(lis):
lis.sort()
if len(lis) % 2 == 0: #even
num = (lis[len(lis) / 2] + lis[(len(lis) / 2) - 1]) / 2.0
else: #odd
num = lis[(len(lis) - 1) / 2]
return num

Thanks!

1 Like

A pencil and paper are great to have on hand for this type of problem, in terms of visualization.

[ , , , , [*], , , , ]

Which element or pair of elements is/are in the middle? What is its index?

sample = [ 41, 94, 38, 76, 59, 25, 19, 63, 81 ]

Count the number of elements.

n = len(sample)

Remember that the first element is index 0. Using integer (or floor) division, find the middle index (or upper pair index).

m = n // 2

In our visual above, what is the index of the middle element? What is m when n is floor divided by 2? 4?

Thanks to fellows like Martin Richards and Edsger W. Dijkstra
we have zero-indexing offering up another advantage in that the quotient of integer division (by 2) of the length of the list either gives us the middle index, or the upper of the two middle indices.

# s = sorted(sample)
return s[m] if n % 2 else (s[m - 1] + s[m]) / 2    # 59

Note: divide by 2.0 if Python 2

One key point to remember when looking for ways to simplify is to identify and cache key data so there are no recurrent patterns. An identity will fill in where needed. Note our m and n variables. There are no methods in the return statement.

I commented out the sort line because it is important for us to see (visualize) the middle element(s) of a list, whether sorted or not. Note that we cached the important data before sorting.

Consider also that the list we are computing the median of may be sensitive to changes. That’s why I use sorted so the parameter is only copied, not mutated. That would re-order the original list and possibly cause problems somewhere else in the program. Lesson here is to never mutate a list in a function unless that is the specific intention. Finding the median of a list does not imply that intention. Best leave the argument list intact.

1 Like

Okay so I’ve failed on the first step lol:

def median(x):
  print x.sort()

median([9, 2, 11, 16, 8, 9])

This returns ‘None’

what does this refer to? the .sort() method or your median function?

if you refer to the .sort() method, have you checked the python documentation about the sort method?