在Python中查找列表的中位数

你如何findPython中列表的中位数? 该列表可以是任何大小的,并且数字不能保证以任何特定顺序。

如果列表包含偶数个元素,则该函数应该返回中间两个的平均值。

以下是一些示例(按显示目的sorting):

median([1]) == 1 median([1, 1]) == 1 median([1, 1, 2, 4]) == 1.5 median([0, 2, 5, 6, 8, 9, 9]) == 6 median([0, 0, 0, 0, 4, 4, 6, 8]) == 2 

Python 3.4有statistics.median

返回数字数据的中位数(中间值)。

当数据点数为奇数时,返回中间数据点。 当数据点的数量是偶数时,通过取两个中间值的平均值来插值中值:

 >>> median([1, 3, 5]) 3 >>> median([1, 3, 5, 7]) 4.0 

用法:

 import statistics items = [1, 2, 3, 6, 8] statistics.median(items) #>>> 3 

types也很小心:

 statistics.median(map(float, items)) #>>> 3.0 from decimal import Decimal statistics.median(map(Decimal, items)) #>>> Decimal('3') 

对于python-2.x :

使用numpy.median()来创build一个单行的函数:

 >>> from numpy import median >>> median([1, -4, -1, -1, 1, -3]) -1.0 

或者, 写一个函数

 def median(lst): n = len(lst) if n < 1: return None if n % 2 == 1: return sorted(lst)[n//2] else: return sum(sorted(lst)[n//2-1:n//2+1])/2.0 

 >>> median([-5, -5, -3, -4, 0, -1]) -3.5 

对于python-3.x ,使用statistics.median

 >>> from statistics import median >>> median([5, 2, 3, 8, 9, -2]) 4.0 

sorted()函数对此非常有帮助。 使用sorting后的函数对列表进行sorting,然后简单地返回中间值(或者如果列表中包含偶数个元素,则平均中间两个值)。

 def median(lst): sortedLst = sorted(lst) lstLen = len(lst) index = (lstLen - 1) // 2 if (lstLen % 2): return sortedLst[index] else: return (sortedLst[index] + sortedLst[index + 1])/2.0 

这是一个更清洁的解决scheme

 def median(lst): quotient, remainder = divmod(len(lst), 2) if remainder: return sorted(lst)[quotient] return sum(sorted(lst)[quotient - 1:quotient + 1]) / 2. 

注意:答案已更改,以在意见中joinbuild议。

如果需要更快的平均运行时间,您可以尝试快速selectalgorithm。 QuickSelect的平均(和最好)的情况下性能O(n) ,虽然它可以在糟糕的一天结束O(n²)

这是一个随机select的支点的实现:

 import random def select_nth(n, items): pivot = random.choice(items) lesser = [item for item in items if item < pivot] if len(lesser) > n: return select_nth(n, lesser) n -= len(lesser) numequal = items.count(pivot) if numequal > n: return pivot n -= numequal greater = [item for item in items if item > pivot] return select_nth(n, greater) 

你可以简单地把它变成一个find中位数的方法:

 def median(items): if len(items) % 2: return select_nth(len(items)//2, items) else: left = select_nth((len(items)-1) // 2, items) right = select_nth((len(items)+1) // 2, items) return (left + right) / 2 

这是非常优化的,但即使是优化的版本也不可能超过Tim Sort(CPython的内置sort ),因为这非常快 。 我已经尝试过,我输了。

您可以使用list.sort来避免创build新的列表,并对列表进行sorted和sorting。

你也不应该使用list作为variables名,因为它会影响python自己的列表 。

 def median(l): half = len(l) // 2 l.sort() if not len(l) % 2: return (l[half - 1] + l[half]) / 2.0 return l[half] 
 def median(array): """Calculate median of the given list. """ # TODO: use statistics.median in Python 3 array = sorted(array) half, odd = divmod(len(array), 2) if odd: return array[half] return (array[half - 1] + array[half]) / 2.0 

在这里,我在Codecademy的这个练习中提出:

 def median(data): new_list = sorted(data) if len(new_list)%2 > 0: return new_list[len(new_list)/2] elif len(new_list)%2 == 0: return (new_list[(len(new_list)/2)] + new_list[(len(new_list)/2)-1]) /2.0 print median([1,2,3,4,5,9]) 

中值函数

 def median(midlist): midlist.sort() lens = len(midlist) if lens % 2 != 0: midl = (lens / 2) res = midlist[midl] else: odd = (lens / 2) -1 ev = (lens / 2) res = float(midlist[odd] + midlist[ev]) / float(2) return res 

我为数字列表定义了一个中值函数

 def median(numbers): return (sorted(numbers)[int(round((len(numbers) - 1) / 2.0))] + sorted(numbers)[int(round((len(numbers) - 1) // 2.0))]) / 2.0 

我在Python中实现了“median of median”algorithm ,这比使用sort()要快一些。 我的解决scheme使用每列15个数字,速度约为5N,比使用每列5个数字的速度约为10N还要快。 最佳速度是~4N,但我可能是错的。

按照Tom的要求,我在这里添加了我的代码,以供参考。 我相信速度的关键部分是每列使用15个数字,而不是5个。

 #!/bin/pypy # # TH @stackoverflow, 2016-01-20, linear time "median of medians" algorithm # import sys, random items_per_column = 15 def find_i_th_smallest( A, i ): t = len(A) if(t <= items_per_column): # if A is a small list with less than items_per_column items, then: # # 1. do sort on A # 2. find i-th smallest item of A # return sorted(A)[i] else: # 1. partition A into columns of k items each. k is odd, say 5. # 2. find the median of every column # 3. put all medians in a new list, say, B # B = [ find_i_th_smallest(k, (len(k) - 1)/2) for k in [A[j:(j + items_per_column)] for j in range(0,len(A),items_per_column)]] # 4. find M, the median of B # M = find_i_th_smallest(B, (len(B) - 1)/2) # 5. split A into 3 parts by M, { < M }, { == M }, and { > M } # 6. find which above set has A's i-th smallest, recursively. # P1 = [ j for j in A if j < M ] if(i < len(P1)): return find_i_th_smallest( P1, i) P3 = [ j for j in A if j > M ] L3 = len(P3) if(i < (t - L3)): return M return find_i_th_smallest( P3, i - (t - L3)) # How many numbers should be randomly generated for testing? # number_of_numbers = int(sys.argv[1]) # create a list of random positive integers # L = [ random.randint(0, number_of_numbers) for i in range(0, number_of_numbers) ] # Show the original list # # print L # This is for validation # # print sorted(L)[int((len(L) - 1)/2)] # This is the result of the "median of medians" function. # Its result should be the same as the above. # print find_i_th_smallest( L, (len(L) - 1) / 2) 

我有一些浮点值列表的问题。 我最终使用python3 statistics.median中的代码片段,并且正在使用没有导入的float值完美工作。 资源

 def calculateMedian(list): data = sorted(list) n = len(data) if n == 0: return None if n % 2 == 1: return data[n // 2] else: i = n // 2 return (data[i - 1] + data[i]) / 2 

这是繁琐的方法来find中位数而不使用中median函数:

 def median(*arg): order(arg) numArg = len(arg) half = int(numArg/2) if numArg/2 ==half: print((arg[half-1]+arg[half])/2) else: print(int(arg[half])) def order(tup): ordered = [tup[i] for i in range(len(tup))] test(ordered) while(test(ordered)): test(ordered) print(ordered) def test(ordered): whileloop = 0 for i in range(len(ordered)-1): print(i) if (ordered[i]>ordered[i+1]): print(str(ordered[i]) + ' is greater than ' + str(ordered[i+1])) original = ordered[i+1] ordered[i+1]=ordered[i] ordered[i]=original whileloop = 1 #run the loop again if you had to switch values return whileloop