पायथन में सूची का माध्यिका खोजना


181

आप पायथन में एक सूची के माध्यिका को कैसे पाते हैं? सूची किसी भी आकार की हो सकती है और संख्या किसी विशेष क्रम में होने की गारंटी नहीं है।

यदि सूची में तत्वों की एक समान संख्या है, तो फ़ंक्शन को मध्य दो के औसत को वापस करना चाहिए।

यहां कुछ उदाहरण दिए गए हैं (प्रदर्शन उद्देश्यों के लिए क्रमबद्ध):

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
यहां उत्तर अच्छे हैं, इसलिए मुझे लगता है कि मैं चाहता हूं कि यह लगभग मध्ययुगीन लोगों को खोजने के लिए एक विहित जवाब हो, मोटे तौर पर इसलिए मैं इसे बंद कर सकता हूं । ध्यान दें कि उस प्रश्न के 30 हजार विचार हैं। अगर यह प्रश्न बंद नहीं होता या किसी भी तरीके से विस्मृत नहीं होता, तो मैं इसकी सराहना करता हूं ताकि यह खोज परिणामों पर बने रह सकें और इसके बजाय उन विचारों को चूस सकें।
विड्राक

जवाबों:


213

अजगर 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जोड़ने के लिए क्वेरी परिणामों में औसत डेटा जोड़ने के लिए। चीयर्स
jamescampbell

क्या होगा यदि आप एक क्रमबद्ध सरणी के माध्य को खोजना चाहते हैं। तो आप फ़ंक्शन सांख्यिकी.मीडिया में निर्मित का उपयोग नहीं कर सकते क्योंकि यह फिर से छँटाई करते समय धीमा हो जाएगा
गिल्बर्ट्स

2
@ गिल्बर्ट तब मध्य तत्व को देखते हैं, या मध्य दो को औसत करते हैं।
वैदिक

163

(के साथ काम करता है ):

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

के लिये , का उपयोग करें statistics.median:

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

9
हालांकि यह एक फ़ंक्शन नहीं लिख रहा है, यह अभी भी एक अधिक "
पायथोनिक

6
@ डार्टडॉग वास्तव में नहीं; यह अच्छे कारण के बिना एक ऊबड़ सरणी के लिए मजबूर करने के लिए अस्वीकार्य है। आपने मनमाने प्रकारों के लिए, खराब और खोए हुए समर्थनों के लिए मजबूर किया है।
विड्राक

1
लिया गया अंक, उपयोगी।
डार्टडॉग

3
हालांकि यह होने के लिए फ़ंक्शन बहुत अधिक श्रमसाध्य है।
मार्टिन पीटर्स

3
PEP 450 एक पुस्तकालय का उपयोग नहीं करने के खिलाफ एक अच्छा तर्क देता है। आप अंततः एक गलती करेंगे।
एलेक्स हार्वे

51

इसके लिए सॉर्ट किया गया () फ़ंक्शन बहुत मददगार है। सूची को क्रम देने के लिए सॉर्ट किए गए फ़ंक्शन का उपयोग करें, फिर केवल मध्य मान लौटाएं (या यदि सूची में तत्वों की एक समान राशि है तो दो मध्य मानों को औसत करें)।

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

हालांकि यह अत्यधिक अक्षम है: मध्यमा (थेटा (n)) के चयन की तुलना में सबसे खराब स्थिति में (थेटा (n lg n)) में छंटनी अधिक काम की है ...
जेरेमी

12

यहाँ एक क्लीनर समाधान है:

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

नोट: टिप्पणियों में सुझाव को शामिल करने के लिए उत्तर बदल गया।


7
float(sum(…) / 2)के साथ प्रतिस्थापित किया जाना चाहिए sum(…) / 2.0; अन्यथा, यदि sum(…)एक पूर्णांक है, तो आपको पूर्णांक भागफल का एक फ्लोट संस्करण मिलेगा। उदाहरण के लिए: float(sum([3, 4]) / 2)है 3.0, लेकिन sum([3, 4]) / 2.0है 3.5
मुसीफिल

पूर्णता के लिए, @ मूसिफ़िल: केवल अजगर 2 में, और केवल अगर आपने नहीं किया है from __future__ import division
क्रिस एल। बार्न्स

11

यदि तेज औसत-केस रनिंग समय की आवश्यकता है, तो आप क्विकसेक एल्गोरिदम की कोशिश कर सकते हैं। क्विकसेलेट में औसत (और सर्वोत्तम) केस प्रदर्शन होता है 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

यह बहुत अकल्पित है, लेकिन यह संभव नहीं है कि एक अनुकूलित संस्करण टिम सॉर्ट (सीपीथॉन के अंतर्निर्मित sort) को भी पछाड़ देगा क्योंकि यह वास्तव में तेज़ है । मैंने पहले भी कोशिश की है और मैं हार गया।


तो क्यों इस बारे में भी सोचें अगर छंटनी () तेज हो?
अधिकतम

@ मोम यदि आप PyPy का उपयोग कर रहे हैं, या कुछ प्रकार जो आप sortआसानी से नहीं कर सकते हैं, या गति के लिए C एक्सटेंशन लिखने के लिए तैयार हैं, आदि
Veedrac

10

बेशक आप कार्यों में निर्माण का उपयोग कर सकते हैं, लेकिन यदि आप अपना खुद का निर्माण करना चाहते हैं तो आप ऐसा कुछ कर सकते हैं। यहाँ चाल ~ संचालक का उपयोग करना है जो सकारात्मक संख्या को नकारात्मक पर फ्लिप करता है। उदाहरण के लिए ~ 2 -> -3 और पायथन में सूची के लिए ऋणात्मक का उपयोग करना अंत से आइटमों की गणना करेगा। इसलिए यदि आपके पास मध्य == 2 है तो यह शुरुआत से तीसरा तत्व और अंत से तीसरा आइटम लेगा।

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

8

आप list.sortनई सूचियों को बनाने से बचने के लिए sortedऔर जगह में सूचियों को क्रमबद्ध करने के लिए उपयोग कर सकते हैं ।

इसके अलावा, आपको 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]

5
सरल उपयोगिता फ़ंक्शंस शायद किसी भी तर्क को उत्परिवर्तित नहीं करना चाहिए (विशेषकर यदि फ़ंक्शन का नाम संज्ञा IMO है)। इसके अलावा सॉर्ट किए गए .sort () का उपयोग करने का अर्थ है कि तर्क की सूची नहीं होनी चाहिए। यह कोई भी पुनरावृत्त हो सकता है।
विल एस

1
मेरी बात सूची को बदलने वाले फ़ंक्शन के बारे में थी। मैंने किसी भी चलने वाले को छँटाई के एक अच्छे पक्ष-प्रभाव के रूप में समर्थन करने का उल्लेख किया, लेकिन यह मुख्य लाभ नहीं है। मुझे उम्मीद है कि लगभग सभी अन्य बिलिन या गणितीय कार्यों की तरह काम करने के लिए माध्यिका (सूची) की उम्मीद होगी। अगला () म्यूट करता है, लेकिन मैं किसी अन्य के बारे में नहीं सोच सकता। डिबगिंग के लिए सरप्राइज म्यूटेशन गधे में एक दर्द है।
विल एस

@WillS, जब इसे प्रलेखित किया जाता है तो यह आश्चर्य की बात कैसे है? क्या होगा यदि आप बड़े डेटा के साथ काम कर रहे हैं या आपके पास मेमोरी की मात्रा सीमित है और आप सूची की एक प्रति नहीं बना सकते हैं, तब क्या है?
पडेरिक कनिंघम

2
फ़ंक्शन को क्रमबद्ध सूची और दस्तावेज़ की अपेक्षा करें। mylist.sort(); middle(mylist), लेकिन तब यह निर्विवाद रूप से स्वाद की बात है। मुझे लगता है कि सामान्य रूप से उत्परिवर्तन को यथासंभव तरीकों के लिए आरक्षित किया जाना चाहिए। सूची के बजाय कारण list.sort () रिटर्न कोई भी नहीं है व्यवहार को यथासंभव स्पष्ट और स्पष्ट करना है। दस्तावेज़ीकरण में सब कुछ छिपाना छोटे-प्रिंट में सामान को छिपाने जैसा है।
विल एस


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
ऐसा लगता है कि कोड की आपकी पहली पंक्ति छोड़ दी गई है, आप इसे अपने पोस्ट को संपादित करके हल कर सकते हैं और फ़ंक्शन हेडर को 4 स्थानों के साथ इंडेंट कर सकते हैं।
जोहान

4

मैंने अपना समाधान "मंझले लोगों के मध्ययुगीन" एल्गोरिथ्म के पायथन कार्यान्वयन पर पोस्ट किया , जो सॉर्ट () का उपयोग करने की तुलना में थोड़ा तेज है। मेरा समाधान प्रति स्तंभ 15 नंबर का उपयोग करता है, एक गति ~ 5N के लिए जो कि प्रति स्तंभ 5 नंबर का उपयोग करने की गति ~ 10N से तेज है। इष्टतम गति ~ 4N है, लेकिन मैं इसके बारे में गलत हो सकता है।

अपनी टिप्पणी में टॉम के अनुरोध के अनुसार, मैंने संदर्भ के लिए अपना कोड यहां जोड़ा। मेरा मानना ​​है कि गति के लिए महत्वपूर्ण हिस्सा 5 के बजाय प्रति कॉलम 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)

3

यहाँ मैं 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

मध्य क्रिया

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

मुझे फ्लोट वैल्यूज़ की सूचियों में कुछ समस्याएँ थीं। मैंने पायथन 3 सांख्यिकी.मीडिया से एक कोड स्निपेट का उपयोग करके समाप्त किया और बिना आयात के फ्लोट मूल्यों के साथ एकदम सही काम कर रहा है। स्रोत

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

मैंने संख्याओं की सूची के लिए एक माध्यिका फ़ंक्शन को परिभाषित किया

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
हालांकि यह कोड प्रश्न का उत्तर दे सकता है, क्यों और / या इस कोड के उत्तर के बारे में अतिरिक्त संदर्भ प्रदान करने से प्रश्न इसके दीर्घकालिक मूल्य में सुधार करता है।
रोलस्टुफ़ेलहेयर 21

1
मैं माफी चाहता हूँ! मैंने अभी शुरू किया, स्टैक ओवरफ्लो, और मुझे नहीं पता कि कैसे एक सारांश जोड़ना है ....
ल्यूक विले

अपनी पोस्ट के नीचे "संपादित करें" लिंक पर क्लिक करें और एक सारांश जोड़ें, फिर सहेजें।
रॉबर्ट कोलंबिया

1

फ़्यूज़न मंझला:

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

यदि आपको अपनी सूची के वितरण पर अतिरिक्त जानकारी की आवश्यकता है, तो प्रतिशतक विधि संभवतः उपयोगी होगी। और एक औसत मूल्य सूची के 50 वें प्रतिशत से मेल खाता है:

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

मंझला (और प्रतिशत) के लिए एक अधिक सामान्यीकृत दृष्टिकोण होगा:

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

0

दी गई सूची के माध्य को लौटाने का एक सरल कार्य:

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

-2

यहाँ 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

क्या यह बबल सॉर्ट है? क्यों?
Ry-

आप मानों की अदला-बदली क्यों कर रहे हैं?
रवि तंवर

-3

यह बहुत ही सरल है;

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)


1
मध्यबिंदु खोजने से पहले मेडियन आपको अपनी सरणी को क्रमबद्ध करने की आवश्यकता है।
सौरभ जैन

sListक्रमबद्ध सरणी वापस करें। मंझला नहीं लौटता
फरहान
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.