পাইথনে তালিকার মাঝারি সন্ধান করা


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 হাজার মতামত আছে। আমি প্রশংসা করব যদি এই প্রশ্নটি কোনওভাবেই বন্ধ বা বিস্মৃত না হয় যাতে এটি অনুসন্ধানের ফলাফলগুলিতে স্থির থাকতে পারে এবং পরিবর্তে those দর্শনগুলি স্তন্যপান করতে পারে।
Veedrac

উত্তর:


213

পাইথন ৩.৪ এর রয়েছে 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ক্যোয়ারির ফলাফলগুলিতে মিডিয়ান ডেটা যুক্ত করার জন্য এটি যুক্ত করার জন্য আমার পক্ষে কাজ করেছে । চিয়ার্স
জামেস্ক্যাম্পবেল

আপনি যদি একটি সাজানো অ্যারের মাঝারি সন্ধান করতে চান তবে কী। সুতরাং আপনি ফাংশন পরিসংখ্যান.মেডিয়ানে অন্তর্নির্মিত ব্যবহার করতে পারবেন না কারণ এটি আবার বাছাইয়ের সময় ধীর হয়ে যাবে
গিলবার্ট

2
@ গিলবার্টস তারপরে মাঝারি উপাদানটি দেখুন বা মাঝারি দুটিকে গড় করুন।
Veedrac

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
পছন্দ করুন উপযুক্ত কারণ ছাড়াই কোনও নম্পি অ্যারেতে বাধ্য করা অযৌক্তিক। আপনি জোর করে প্রকারভেদ করেছেন এবং স্বেচ্ছাসেবী প্রকারের জন্য সমর্থন হারিয়েছেন।
Veedrac

1
পয়েন্ট নেওয়া, দরকারী।
ডার্টডগ

3
যদিও এটি করা দরকার তার চেয়ে অনেক বেশি শ্রমসাধ্য কাজ।
মার্টিজন পিটারস

3
পিইপি 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

এটি অত্যন্ত অদক্ষ হলেও: বাছাইয়ের কাজটি মধ্যস্থতাকে বেছে নেওয়ার চেয়ে (থেটা (এন lg এন)) সবচেয়ে বেশি কাজ (থেটা (এন)) ...
জেরেমি

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) ছাড়িয়ে যাবে কারণ এটি সত্যই দ্রুত । আমি আগে চেষ্টা করেছি এবং আমি হেরেছি।


সুতরাং এমনকি যদি এই সম্পর্কে কেন ভাবেন যদি সাজানোর () দ্রুত হয়?
সর্বোচ্চ

@ ম্যাক্স আপনি যদি পাইপি ব্যবহার করেন, বা কোনও প্রকার আপনি sortসহজেই পারবেন না , বা গতির জন্য কোনও সি এক্সটেনশন লিখতে ইচ্ছুক
নন

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
সাধারণ ইউটিলিটি ফাংশনগুলিতে সম্ভবত কোনও যুক্তি পরিবর্তন করা উচিত নয় (বিশেষত যদি ফাংশনটির নাম একটি আইএমও হয়)। এছাড়াও .sort () এর উপরে বাছাই করা মানে আর্গুমেন্টের কোনও তালিকা থাকতে হবে না। এটি যে কোনও পুনরাবৃত্তকারী হতে পারে।
এস ই

1
আমার বক্তব্য ছিল তালিকার পরিবর্তনকারী ফাংশন সম্পর্কে। আমি সাজানো একটি দুর্দান্ত পার্শ্ব প্রতিক্রিয়া হিসাবে যে কোনও পুনরাবৃত্তযোগ্য সমর্থন সমর্থন উল্লেখ, কিন্তু এটি প্রধান সুবিধা নয়। আমি একজনের কাছে মধ্যবর্তী (তালিকা) প্রায় অন্যান্য বিল্টিন বা গাণিতিক ফাংশনের মতো কাজ করার আশা করব। পরবর্তী () রূপান্তরিত হয়, তবে আমি অন্য কোনওটির কথা ভাবতে পারি না। বিস্ময়ের পরিবর্তনটি ডিবাগিংয়ের জন্য পাছার একটি ব্যথা।
উইল এস

@ উইলস, এটি নথিভুক্ত করা হলে এটি কীভাবে অবাক হবে? আপনি যদি বড় ডেটা নিয়ে কাজ করছেন বা আপনি পরিমাণের মেমোরি সীমিত রেখেছেন এবং আপনি তালিকার একটি অনুলিপি তৈরি করতে না পারেন তবে কী?
প্যাডেরিক কানিংহাম

2
ক্রিয়াকলাপটি একটি সাজানো তালিকা এবং নথির প্রত্যাশা তৈরি করুন। mylist.sort(); middle(mylist), তবে তারপরে এটি অনস্বীকার্যভাবে স্বাদের বিষয়। আমি কেবল মনে করি সাধারণভাবে পরিব্যক্তি যতটা সম্ভব পদ্ধতিগুলির জন্য সংরক্ষণ করা উচিত। কারণের তালিকা.সোর্ট () তালিকার পরিবর্তে আর কিছুই প্রত্যাবর্তন করে না তা আচরণটি যতটা সম্ভব স্পষ্ট এবং স্পষ্ট করে তোলা। ডকুমেন্টেশনে সমস্ত কিছু আড়াল করা ছোট প্রিন্টে থাকা জিনিসগুলি আড়াল করার মতো।
উইল এস


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

কোডেক্যাডেমিতে এই মহড়ার সময় আমি কী নিয়ে এসেছি:

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

এটি কি বুদ্বুদ সাজান? কেন?
রাই-

আপনি মান অদলবদল হয় কেন?
রবি তানওয়ার

-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সাজানো অ্যারে ফিরিয়ে দিন মিডিয়ান ফিরিয়ে দেয় না
ফারহান
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.