3

I have stumbled upon this pure python implementation for calculating percentiles here and here:

import math
import functools

def percentile(N, percent, key=lambda x:x):
"""
Find the percentile of a list of values.

@parameter N - is a list of values. Note N MUST BE already sorted.
@parameter percent - a float value from 0.0 to 1.0.
@parameter key - optional key function to compute value from each element of N.

@return - the percentile of the values
"""
   if not N:
       return None
   k = (len(N)-1) * percent
   f = math.floor(k)
   c = math.ceil(k)
   if f == c:
       return key(N[int(k)])
   d0 = key(N[int(f)]) * (c-k)
   d1 = key(N[int(c)]) * (k-f)
   return d0+d1

I get the basic principle behind this function and i see that it works correctly:

>>> percentile(range(10),0.25)
2.25

What I don't get is what the lambda function key=lambda x:x is there for. As far as i unterstand it, this lambda function simply returns the value that is passed to it. Basically, the whole function seems to yield the same result if i omit this lambda function altogether:

import math

def percentile2(N, percent):
"""
Find the percentile of a list of values.

@parameter N - is a list of values. Note N MUST BE already sorted.
@parameter percent - a float value from 0.0 to 1.0.
@parameter key - REMOVED

@return - the percentile of the values
"""
   if not N:
       return None
   k = (len(N)-1) * percent
   f = math.floor(k)
   c = math.ceil(k)
   if f == c:
       return N[int(k)]
   d0 = N[int(f)] * (c-k)
   d1 = N[int(c)] * (k-f)
   return d0+d1

If I test this:

>>> percentile2(range(10),0.25)
2.25

So what is the use of that lambda function, here?

Community
  • 1
  • 1
jov14
  • 139
  • 9
  • just edited to remove that last remaining call of the "key" function from the percentile2() function – jov14 Jun 03 '16 at 21:11

3 Answers3

7

The answer is right there in the docstring (the string that starts on the line after the def statement):

@parameter key - optional key function to compute value from each element of N.

This allows you to use a list of something other than numbers. For example, your lambda could be lambda x:x.getRelevantValue() and your list would be one containing objects that have a getRelevantValue method.

Rob Watts
  • 6,866
  • 3
  • 39
  • 58
  • Thanks for clearing that. I just did not understand that doc-line because my familiarity with lambda functions (and apparently objects in python for that matter) is still limited. But my assumption that this percentile function works correctly for calculating percentiles in all cases of simple integer ranges if I omit the lamda function is correct, yes? – jov14 Jun 03 '16 at 21:21
  • @John I can't vouch for the correctness of the function ;) but yes with the default lambda function the lambda function does nothing and so can be omitted. – Rob Watts Jun 03 '16 at 21:25
2

It's right there in the documentation of the function:

@parameter key - optional key function to compute value from each element of N.

Basically, the percentile function allows the user to optionally pass a key function which will be applied to the elements of N. Since it is optional, it has been given the default value lambda x:x, which does nothing, so the function works even if the user omits the key parameter.

Aran-Fey
  • 39,665
  • 11
  • 104
  • 149
  • Thanks, I read that documentation line but i hadn't understood it. I think i get it now but I still have to get more used to the flexibility of lambda functions. – jov14 Jun 03 '16 at 21:18
-5

It's a tie-breaker in case f ever equals c. You haven't come across such a case, so your code never blows up (since key now doesn't exist).

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • 1
    wow that was a fast response. But isn't the tie breaker the "if" statement returning N[int(k)] in case it is True? (I just forgot to remove the key function from that line). – jov14 Jun 03 '16 at 21:09