您如何在Python中找到列表的中位数?该列表可以是任何大小,并且不能保证数字以任何特定顺序排列。
如果列表包含偶数个元素,则该函数应返回中间两个元素的平均值。
以下是一些示例(排序用于显示目的):
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中找到列表的中位数?该列表可以是任何大小,并且不能保证数字以任何特定顺序排列。
如果列表包含偶数个元素,则该函数应返回中间两个元素的平均值。
以下是一些示例(排序用于显示目的):
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
Answers:
Python 3.4具有statistics.median
:
返回数值数据的中位数(中间值)。
当数据点数为奇数时,返回中间数据点。当数据点的数量为偶数时,通过取两个中间值的平均值来对中位数进行插值:
>>> median([1, 3, 5]) 3 >>> median([1, 3, 5, 7]) 4.0
用法:
import statistics
items = [6, 1, 8, 2, 3]
statistics.median(items)
#>>> 3
类型也非常小心:
statistics.median(map(float, items))
#>>> 3.0
from decimal import Decimal
statistics.median(map(Decimal, items))
#>>> Decimal('3')
pip3 install itunizer
添加到查询结果中添加中值数据。干杯
(与 python-2.x):
def median(lst):
n = len(lst)
s = sorted(lst)
return (sum(s[n//2-1:n//2+1])/2.0, s[n//2])[n % 2] if n else None
>>> median([-5, -5, -3, -4, 0, -1])
-3.5
>>> from numpy import median
>>> median([1, -4, -1, -1, 1, -3])
-1.0
对于 python-3.x,使用statistics.median
:
>>> from statistics import median
>>> median([5, 2, 3, 8, 9, -2])
4.0
sorted()函数对此很有帮助。使用排序功能对列表进行排序,然后简单地返回中间值(如果列表包含偶数个元素,则对两个中间值求平均值)。
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
这是一个更清洁的解决方案:
def median(lst):
quotient, remainder = divmod(len(lst), 2)
if remainder:
return sorted(lst)[quotient]
return sum(sorted(lst)[quotient - 1:quotient + 1]) / 2.
注意:答案已更改为将建议纳入注释中。
float(sum(…) / 2)
应该换成sum(…) / 2.0
; 否则,如果sum(…)
为整数,则将获得整数商的浮点型。例如:float(sum([3, 4]) / 2)
is 3.0
,但是sum([3, 4]) / 2.0
is 3.5
。
from __future__ import division
。
如果需要更快的平均情况运行时间,则可以尝试使用quickselect算法。O(n)
尽管Quickselect 可能会O(n²)
遇到糟糕的一天,但它具有平均(和最佳)的案例性能。
这是一个随机选择的实现的实现:
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)
您可以简单地将其转换为查找中位数的方法:
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
),因为这确实非常快。我以前尝试过,但输了。
sort
容易,或者愿意为速度编写C扩展名等
您可以使用list.sort
来避免使用创建新列表sorted
并在适当位置对列表进行排序。
另外,您不应使用它list
作为变量名,因为它会遮盖python自己的list。
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]
mylist.sort(); middle(mylist)
,但毫无疑问,这是一个品味问题。我只是认为,一般而言,变异应尽可能保留给方法。list.sort()返回None而不是列表本身的原因是为了使行为尽可能明显和清楚。将所有内容隐藏在文档中就像将内容隐藏在小字体中。
我在“中位数中值”算法的Python实现中发布了我的解决方案,它比使用sort()快一点。我的解决方案每列使用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)
中位数函数
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
我在浮点值列表方面遇到了一些问题。我最终使用了来自python3 statistics.median的代码片段,并且可以完美地处理没有导入的浮点值。资源
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
def median(array):
if len(array) < 1:
return(None)
if len(array) % 2 == 0:
median = (array[len(array)//2-1: len(array)//2+1])
return sum(median) / len(median)
else:
return(array[len(array)//2])
import numpy as np
def get_median(xs):
mid = len(xs) // 2 # Take the mid of the list
if len(xs) % 2 == 1: # check if the len of list is odd
return sorted(xs)[mid] #if true then mid will be median after sorting
else:
#return 0.5 * sum(sorted(xs)[mid - 1:mid + 1])
return 0.5 * np.sum(sorted(xs)[mid - 1:mid + 1]) #if false take the avg of mid
print(get_median([7, 7, 3, 1, 4, 5]))
print(get_median([1,2,3, 4,5]))
中位数(和百分位数)的更通用方法是:
def get_percentile(data, percentile):
# Get the number of observations
cnt=len(data)
# Sort the list
data=sorted(data)
# Determine the split point
i=(cnt-1)*percentile
# Find the `floor` of the split point
diff=i-int(i)
# Return the weighted average of the value above and below the split point
return data[int(i)]*(1-diff)+data[int(i)+1]*(diff)
# Data
data=[1,2,3,4,5]
# For the median
print(get_percentile(data=data, percentile=.50))
# > 3
print(get_percentile(data=data, percentile=.75))
# > 4
# Note the weighted average difference when an int is not returned by the percentile
print(get_percentile(data=data, percentile=.51))
# > 3.04
一个简单的函数返回给定列表的中位数:
def median(lsts):
if len(lsts)%2 == 0: #Checking if the length is even
return (lsts[len(lsts)//2] + lsts[(len(lsts) - 1) //2]) //2 # Applying formula which is sum of middle two divided by 2
else:
return lsts[len(lsts)//2] # If length is odd then get middle value
median([2,3,5,6,10]) #Calling function
如果您想使用库,则只需做一下即可;
import statistics
statistics.median([9, 12, 20, 21, 34, 80])
这是不使用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