web-dev-qa-db-ja.com

Pythonでリストの中央値を見つける

どのようにしてPythonのリストの中央値を見つけますか?リストは任意のサイズにすることができ、番号は特定の順序になるとは限りません。

リストに偶数個の要素が含まれている場合、関数は中央の2つの平均を返します。

これがいくつかの例です(表示目的でソートされています)。

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
140
ChucksPlace

Python 3.4には statistics.median があります。

数値データの中央値(中央値)を返します。

データ点数が奇数の場合は、中央のデータ点を返します。データ点の数が偶数の場合、中央値は2つの中央値の平均をとることによって補間されます。

>>> 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')
156
Veedrac

python-2.x :の場合

単一行の関数を作るには numpy.median() を使います:

>>> 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
138
A.J. Uppal

Sorted()関数はこれにとても役に立ちます。ソートされた関数を使用してリストの順序を決めてから、単に中間値を返します(または、リストに偶数の要素が含まれる場合は2つの中間値を平均します)。

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
45
swolfe

これがよりきれいな解決策です:

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

注:コメントに提案を含めるように回答が変更されました。

12
Batuhan Ulug

より速い平均実行時間が必要な場合は、 quickselect アルゴリズムを試すことができます。クイックセレクトは、平均的な(そして最良の)ケースパフォーマンスO(n)を持ちますが、悪い日には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)より優れているとは限りません。これは本当に速いです。

9
Veedrac

もちろん、組み込み関数を使用することもできますが、独自に作成したい場合は、次のようにすることができます。ここでの秘訣は、正の数を負の数に反転させる〜演算子を使うことです。例えば、〜2 - > -3で、Pythonでforリストに否定を使用すると、項目は最後から数えられます。あなたがmid == 2を持っているのであれば、それは最初から3番目の要素と最後から3番目の要素を取ります。

def median(data):
    data.sort()
    mid = len(data) // 2
    return (data[mid] + data[~mid]) / 2
9
Vlad Bezden

sortedを使用して新しいリストを作成しないようにし、リストを適切にソートするには、list.sortを使用できます。

また、python独自の list を隠すので、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]
8
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
7
warvariuc
def median(x):
    x = sorted(x)
    listlength = len(x) 
    num = listlength//2
    if listlength%2==0:
        middlenum = (x[num]+x[num-1])/2
    else:
        middlenum = x[num]
    return middlenum
5
Bulent

ここで私は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])
3
BynderRox
def midme(list1):

    list1.sort()
    if len(list1)%2>0:
            x = list1[int((len(list1)/2))]
    else:
            x = ((list1[int((len(list1)/2))-1])+(list1[int(((len(list1)/2)))]))/2
    return x


midme([4,5,1,7,2])
2
vk123

Float値のリストに問題がありました。私は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
2
Daniel

中央値関数

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

私の解決策は Pythonによる "median of medians"アルゴリズムの実装 で、これはsort()を使うよりも少し速いです。私のソリューションでは、列ごとに15個の数字を使用します。これは、列ごとに5個の数字を使用する場合の最大10Nの速度よりも速い最大5Nの速度の場合です。最適な速度は4Nですが、私はそれについては間違っているかもしれません。

Tomさんのコメントで、私のコードを参考のためにここに追加しました。私はスピードの重要な部分は5の代わりに1列あたり15の数字を使うことだと思います。

#!/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)
2
user5818263
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])
1
Luke Willey

数のリストの中央値関数を次のように定義しました。

def median(numbers):
    return (sorted(numbers)[int(round((len(numbers) - 1) / 2.0))] + sorted(numbers)[int(round((len(numbers) - 1) // 2.0))]) / 2.0
1
Fred Beck
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]))
0
sim

とても簡単です。

def median(alist):
    #to find median you will have to sort the list first
    sList = sorted(alist)
    first = 0
    last = len(sList)-1
    midpoint = (first + last)//2
    return midpoint

そして、あなたはこのような戻り値を使うことができますmedian = median(anyList)

0
Farhan