web-dev-qa-db-fra.com

Trouver la médiane de la liste en Python

Comment trouvez-vous la médiane d'une liste dans Python? La liste peut être de n'importe quelle taille et les nombres ne sont pas garantis dans un ordre particulier.

Si la liste contient un nombre pair d'éléments, la fonction doit renvoyer la moyenne des deux médians.

Voici quelques exemples (triés pour l'affichage):

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

Python 3.4 a statistics.median :

Renvoie la médiane (valeur moyenne) des données numériques.

Lorsque le nombre de points de données est impair, retourne le point de données intermédiaire . Lorsque le nombre de points de données est pair, la médiane est interpolée en prenant la moyenne des deux valeurs centrales:

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

Usage:

import statistics

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

statistics.median(items)
#>>> 3

C'est assez prudent avec les types aussi:

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

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

Pour python-2.x :

Utilisez numpy.median() pour créer une fonction sur une ligne:

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

Ou, pour écrire une fonction :

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

Pour python-3.x , utilisez statistics.median :

>>> from statistics import median
>>> median([5, 2, 3, 8, 9, -2])
4.0
128
A.J. Uppal

La fonction triée () est très utile pour cela. Utilisez la fonction triéepour ordonner la liste, puis renvoyez simplement la valeur centrale (ou faites la moyenne des deux valeurs moyennes Si la liste contient un nombre pair d’éléments).

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

Voici une solution plus propre:

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

Remarque: La réponse a été modifiée pour intégrer la suggestion dans les commentaires.

11
Batuhan Ulug

Vous pouvez essayer l’algorithme quickselect si des temps d’exécution plus rapides sont nécessaires. Quickselect a des performances de cas moyennes (et meilleures) O(n), bien que O(n²) puisse se terminer un mauvais jour.

Voici une implémentation avec un pivot choisi au hasard:

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)

Vous pouvez facilement transformer ceci en une méthode de recherche de médianes:

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

Ceci est très peu optimisé, mais il est peu probable que même une version optimisée surpasse Tim Sort (sort intégré de CPython) car c'est vraiment rapide. J'ai déjà essayé et j'ai perdu.

8
Veedrac

Bien sûr, vous pouvez utiliser les fonctions intégrées, mais si vous voulez créer les vôtres, vous pouvez faire quelque chose comme ça. Le truc ici consiste à utiliser ~ opérateur qui renverse le nombre positif en négatif. Par exemple, ~ 2 -> -3 et utiliser Négatif dans une liste en Python comptera les éléments à la fin. Donc, si vous avez mid == 2, il faudra le troisième élément du début et le troisième élément de la fin.

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

Vous pouvez utiliser le list.sort pour éviter de créer de nouvelles listes avec sorted et trier les listes en place.

De plus, vous ne devriez pas utiliser list comme nom de variable car elle ombrage le propre list de 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]
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
6
warvariuc

Voici ce que je suis venu avec cet exercice dans 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])
2
BynderRox
import numpy as np
def median(x):

    if len(x)%2==0:
        x = sorted(x)
        num = round(len(x)/2)
        num2 = num-1
        middlenum = (x[num]+x[num2])/2
    else:
        x = sorted(x)
        listlength = len(x) 
        num = round(listlength / 2)
        middlenum = x[num]
    return middlenum
2
Bulent
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
vk123

J'ai eu quelques problèmes avec les listes de valeurs flottantes. J'ai fini par utiliser un extrait de code de python3 statistics.median et fonctionne parfaitement avec des valeurs float sans importations. la source

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

Fonction médiane

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

J'ai posté ma solution sur Implémentation Python de l'algorithme "median of medians" , ce qui est un peu plus rapide que d'utiliser sort (). Ma solution utilise 15 nombres par colonne, pour une vitesse ~ 5N qui est plus rapide que la vitesse ~ 10N d'utilisation de 5 nombres par colonne. La vitesse optimale est de ~ 4N, mais je peux me tromper à ce sujet.

Par demande de Tom dans son commentaire, j'ai ajouté mon code ici, pour référence. Je crois que la partie critique pour la vitesse utilise 15 nombres par colonne au lieu de 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)
1
user5818263
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(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])
0
Luke Willey

J'ai défini une fonction médiane pour une liste de nombres comme

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

C'est très simple;

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

Et vous pouvez utiliser la valeur de retour comme celle-ci median = median(anyList)

0
Farhan