Median der Liste in Python finden


181

Wie finden Sie den Median einer Liste in Python? Die Liste kann beliebig groß sein und es wird nicht garantiert, dass die Nummern in einer bestimmten Reihenfolge vorliegen.

Wenn die Liste eine gerade Anzahl von Elementen enthält, sollte die Funktion den Durchschnitt der beiden mittleren Elemente zurückgeben.

Hier einige Beispiele (für Anzeigezwecke sortiert):

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


9
Die Antworten hier sind gut, daher denke ich, dass dies ungefähr eine kanonische Antwort für die Suche nach Medianwerten sein soll, hauptsächlich, damit ich dies schließen kann . Beachten Sie, dass diese Frage 30.000 Aufrufe hat. Ich würde mich freuen, wenn diese Frage nicht geschlossen oder in irgendeiner Weise vergessen würde, damit sie in den Suchergebnissen bleibt und stattdessen diese Ansichten aufnimmt.
Veedrac

Antworten:


213

Python 3.4 hat statistics.median:

Gibt den Median (Mittelwert) der numerischen Daten zurück.

Wenn die Anzahl der Datenpunkte ungerade ist, geben Sie den mittleren Datenpunkt zurück. Wenn die Anzahl der Datenpunkte gerade ist, wird der Median interpoliert, indem der Durchschnitt der beiden Mittelwerte genommen wird:

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

Verwendung:

import statistics

items = [6, 1, 8, 2, 3]

statistics.median(items)
#>>> 3

Auch bei Typen ist es ziemlich vorsichtig:

statistics.median(map(float, items))
#>>> 3.0

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

Perfekt, ich habe es hinzugefügt pip3 install itunizer, um Median-Daten zu den Abfrageergebnissen hinzuzufügen. Prost
Jamescampbell

Was ist, wenn Sie den Median eines sortierten Arrays ermitteln möchten? Sie können also die integrierte Funktion statistics.median nicht verwenden, da sie beim erneuten Sortieren langsamer wird
GilbertS

2
@GilbertS Dann schauen Sie sich das mittlere Element an oder mitteln Sie die mittleren beiden.
Veedrac

163

(Arbeitet mit ):

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

numpy.median()::

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

Zum , benutze statistics.median:

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

9
Während es keine Funktion schreibt, ist es immer noch eine "pythonischere" Lösung imho
dartdog

6
@dartdog Nicht wirklich; Es ist nicht ratsam, ohne guten Grund zu einem Numpy-Array zu zwingen. Sie haben Typen gezwungen und, schlimmer noch, die Unterstützung für beliebige Typen verloren.
Veedrac

1
Punkte genommen, nützlich.
Dartdog

3
Die Funktion ist jedoch viel mühsamer als nötig.
Martijn Pieters

3
PEP 450 ist ein gutes Argument gegen die Nichtverwendung einer Bibliothek. Sie werden irgendwann einen Fehler machen.
Alex Harvey

51

Die Funktion sortiert () ist hierfür sehr hilfreich. Verwenden Sie die sortierte Funktion, um die Liste zu ordnen, und geben Sie dann einfach den Mittelwert zurück (oder mitteln Sie die beiden Mittelwerte, wenn die Liste eine gerade Anzahl von Elementen enthält).

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

Es ist jedoch sehr ineffizient: Sortieren ist im schlimmsten Fall (Theta (n lg n)) viel mehr Arbeit als das Auswählen des Medians (Theta (n)) ...
Jeremy

12

Hier ist eine sauberere Lösung:

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

Hinweis: Die Antwort wurde geändert, um Vorschläge in Kommentare aufzunehmen.


7
float(sum(…) / 2)sollte ersetzt werden durch sum(…) / 2.0; Andernfalls erhalten Sie, wenn sum(…)es sich um eine Ganzzahl handelt, eine Float-Version des Ganzzahlquotienten. Zum Beispiel: float(sum([3, 4]) / 2)ist 3.0, aber sum([3, 4]) / 2.0ist 3.5.
Musiphil

Der Vollständigkeit halber @musiphil: nur in Python 2 und nur, wenn Sie es nicht getan haben from __future__ import division.
Chris L. Barnes

11

Sie können den Schnellauswahlalgorithmus ausprobieren , wenn schnellere Durchschnittslaufzeiten erforderlich sind. Quickselect bietet eine durchschnittliche (und beste) Fallleistung O(n), obwohl es O(n²)an einem schlechten Tag enden kann .

Hier ist eine Implementierung mit einem zufällig ausgewählten Pivot:

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)

Sie können dies trivial in eine Methode verwandeln, um Mediane zu finden:

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

Dies ist sehr unoptimiert, aber es ist unwahrscheinlich, dass selbst eine optimierte Version Tim Sort (CPythons integrierte Version) übertrifft, sortda dies sehr schnell ist . Ich habe es schon einmal versucht und ich habe verloren.


Warum also überhaupt darüber nachdenken, wenn sort () schneller ist?
Max

@ Max Wenn Sie PyPy oder einen Typ verwenden, können Sie nicht sorteinfach oder bereit sein, eine C-Erweiterung für Geschwindigkeit usw. zu schreiben.
Veedrac

10

Natürlich können Sie eingebaute Funktionen verwenden, aber wenn Sie Ihre eigenen erstellen möchten, können Sie so etwas tun. Der Trick dabei ist, den Operator ~ zu verwenden, der die positive Zahl auf die negative umdreht. Zum Beispiel zählt ~ 2 -> -3 und die Verwendung von Negativ in für Liste in Python die Elemente vom Ende. Wenn Sie also mid == 2 haben, wird das dritte Element vom Anfang und das dritte Element vom Ende genommen.

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

8

Sie können das verwenden list.sort, um das Erstellen neuer Listen mit zu vermeiden und die vorhandenen Listen zu sortedsortieren.

Sie sollten es auch nicht listals Variablennamen verwenden, da es die eigene Liste von Python beschattet .

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]

5
Einfache Dienstprogrammfunktionen sollten wahrscheinlich keine Argumente mutieren (insbesondere wenn der Funktionsname ein Substantiv IMO ist). Die Verwendung von sortiert über .sort () bedeutet auch, dass das Argument keine Liste sein muss. Es könnte jeder Iterator sein.
Will S

1
Mein Punkt war über die Funktion, die die Liste mutiert. Ich erwähnte die Unterstützung von iterable als einen netten Nebeneffekt von sortiert, aber das ist nicht der Hauptvorteil. Ich würde erwarten, dass der Median (Liste) wie fast alle anderen eingebauten oder mathematischen Funktionen funktioniert. next () mutiert, aber ich kann mir keine anderen vorstellen. Überraschungsmutation ist ein Schmerz im Arsch für das Debuggen.
Will S

@ WillS, wie ist es eine Überraschung, wenn es dokumentiert ist? Was ist, wenn Sie mit großen Datenmengen arbeiten oder nur über begrenzten Speicher verfügen und keine Kopie der Liste erstellen können? Was dann?
Padraic Cunningham

2
Lassen Sie die Funktion eine sortierte Liste erwarten und dokumentieren Sie diese. mylist.sort(); middle(mylist), aber dann ist es unbestreitbar Geschmackssache. Ich denke nur, dass Mutationen im Allgemeinen so weit wie möglich Methoden vorbehalten sein sollten. Der Grund, warum list.sort () None anstelle der Liste selbst zurückgibt, besteht darin, das Verhalten so offensichtlich und klar wie möglich zu gestalten. Alles in der Dokumentation zu verstecken ist wie etwas im Kleingedruckten zu verstecken.
Will S


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

1
Es sieht so aus, als ob Ihre erste Codezeile weggelassen wurde. Sie können dies lösen, indem Sie Ihren Beitrag bearbeiten und den Funktionsheader mit 4 Leerzeichen einrücken.
Johan

4

Ich habe meine Lösung bei der Python-Implementierung des "Median of Medians" -Algorithmus veröffentlicht , der etwas schneller ist als die Verwendung von sort (). Meine Lösung verwendet 15 Zahlen pro Spalte für eine Geschwindigkeit von ~ 5 N, was schneller ist als die Geschwindigkeit von ~ 10 N bei Verwendung von 5 Zahlen pro Spalte. Die optimale Geschwindigkeit ist ~ 4N, aber ich könnte mich irren.

Auf Toms Bitte in seinem Kommentar habe ich meinen Code hier als Referenz hinzugefügt. Ich glaube, der entscheidende Teil für die Geschwindigkeit ist die Verwendung von 15 Zahlen pro Spalte anstelle von 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)

3

Folgendes habe ich mir während dieser Übung in der Codecademy ausgedacht:

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])

2

Medianfunktion

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

2

Ich hatte einige Probleme mit Listen von Float-Werten. Am Ende habe ich ein Code-Snippet aus der Datei python3 statistics.median verwendet und arbeite perfekt mit Float-Werten ohne Import. Quelle

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
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])

1

Ich habe eine Medianfunktion für eine Liste von Zahlen als definiert

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
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])

3
Während dieser Code die Frage möglicherweise beantwortet, verbessert die Bereitstellung eines zusätzlichen Kontexts darüber, warum und / oder wie dieser Code die Frage beantwortet, ihren langfristigen Wert.
Rollstuhlfahrer

1
Es tut mir sehr leid! Ich habe gerade angefangen, Stack Overflow, und ich weiß nicht, wie ich eine Zusammenfassung hinzufügen soll ...
Luke Willey

Klicken Sie auf den Link "Bearbeiten" unter Ihrem Beitrag, fügen Sie eine Zusammenfassung hinzu und speichern Sie sie.
Robert Columbia

1

Funktionsmedian:

def median(d):
    d=np.sort(d)
    n2=int(len(d)/2)
    r=n2%2
    if (r==0):
        med=d[n2] 
    else:
        med=(d[n2] + data[m+1]) / 2
    return med

1

Falls Sie zusätzliche Informationen zur Verteilung Ihrer Liste benötigen, ist die Perzentilmethode wahrscheinlich hilfreich. Ein Medianwert entspricht dem 50. Perzentil einer Liste:

import numpy as np
a = np.array([1,2,3,4,5,6,7,8,9])
median_value = np.percentile(a, 50) # return 50th percentile
print median_value 

0
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

Ein allgemeinerer Ansatz für Median (und Perzentile) wäre:

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

-2

Hier ist der mühsame Weg, den Median zu finden, ohne die medianFunktion zu verwenden:

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

Ist das Blasensorte? Warum?
Ry-

Warum tauschen Sie Werte aus?
Ravi Tanwar

-3

Es ist sehr einfach;

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

Und Sie können den Rückgabewert so verwenden median = median(anyList)


1
Im Median müssen Sie Ihr Array sortieren, bevor Sie den Mittelpunkt finden.
Saurabh Jain

sListGeben Sie das sortierte Array zurück. Gibt den Median nicht zurück
Farhan
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.