আইটেমের ক্রম বজায় রেখে তালিকা থেকে এলোমেলো নমুনা পান?


84

আমার একটি বাছাই করা তালিকা রয়েছে, বলুন: (এটি সত্যিকারের সংখ্যা নয়, এটি একটি জটিল সময় গ্রহণকারী অ্যালগরিদমের সাথে বাছাই করা অবজেক্টগুলির একটি তালিকা)

mylist = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ,9  , 10 ]

এমন কোনও অজগর ফাংশন রয়েছে যা আমাকে আইটেমগুলির জন্য এন দেবে, তবে ক্রমটি রাখবে?

উদাহরণ:

randomList = getRandom(mylist,4)
# randomList = [ 3 , 6 ,7 , 9 ]
randomList = getRandom(mylist,4)
# randomList = [ 1 , 2 , 4 , 8 ]

ইত্যাদি ...


4
আপনি কেন random.sampleএবং তারপর বাছাই করতে চান না ?
ড্যানিয়েল লুবারভ

এটি একটি তুচ্ছ অ্যালগরিদম দিয়ে সাজানো ... এটি কেবলমাত্র সংখ্যা নয়
ইয়োচাই টিমারের

4
ড্যানিয়েলের মন্তব্যে খুব সামান্য পরিবর্তন: একটি পরিসীমা নমুনা করুন, নমুনাকে [0,count)বাছাই করুন (পরিসরের সংখ্যাগুলির একটি প্রাকৃতিক ক্রম রয়েছে), তারপরে mylistসূচকগুলির উপর ভিত্তি করে মানগুলি বের করুন । ব্যবহার zipকিছুটা ভিন্ন যান্ত্রিকতার সাথে একই প্রভাব অর্জন করতে পারে।

4
ঠিক আছে, আমি কি উত্তর + উদাহরণ পেতে পারি তাই আমার কিছু গ্রহণ করার আছে? :)
ইয়োচাই টিমমার

উত্তর:


121

নিম্নলিখিত কোড 4 মাপের এলোমেলো নমুনা উত্পন্ন করবে:

import random

sample_size = 4
sorted_sample = [
    mylist[i] for i in sorted(random.sample(range(len(mylist)), sample_size))
]

(দ্রষ্টব্য: পাইথন 2 সহ এর xrangeপরিবর্তে আরও ভাল ব্যবহার করুন range)

ব্যাখ্যা

random.sample(range(len(mylist)), sample_size)

মূল তালিকার সূচকের একটি এলোমেলো নমুনা উত্পন্ন করে ।

এই সূচকগুলি পরে মূল তালিকার উপাদানগুলির ক্রম সংরক্ষণের জন্য সাজানো হয়।

পরিশেষে, নমুনা সূচকগুলি বিবেচনা করে তালিকা বোধগম্যতা মূল তালিকা থেকে আসল উপাদানগুলি বের করে।


89

সরল-থেকে-কোড হে (এন + কে * লগ (কে)) উপায়

সূচকগুলি প্রতিস্থাপন ছাড়াই এলোমেলো নমুনা নিন, সূচকগুলি বাছাই করুন এবং সেগুলি মূল থেকে নেওয়া।

indices = random.sample(range(len(myList)), K)
[myList[i] for i in sorted(indices)]

বা আরও সংক্ষিপ্তভাবে:

[x[1] for x in sorted(random.sample(enumerate(myList),K))]

অপ্টিমাইজড ও (এন) -সময়ের, হে (1) -অক্সিলিয়ারি-স্পেস ওয়ে

আপনি বৈকল্পিকভাবে একটি গণিতের কৌশল ব্যবহার করতে পারেন এবং পুনরাবৃত্তভাবে myListবাম থেকে ডানে যেতে পারেন , পরিবর্তনশীল-পরিবর্তনের সম্ভাবনার সাথে সংখ্যাগুলি বাছাই করে (N-numbersPicked)/(total-numbersVisited)। এই পদ্ধতির সুবিধা হ'ল এটি একটি O(N)অ্যালগরিদম যেহেতু এটি বাছাইয়ের সাথে জড়িত নয়!

from __future__ import division

def orderedSampleWithoutReplacement(seq, k):
    if not 0<=k<=len(seq):
        raise ValueError('Required that 0 <= sample_size <= population_size')

    numbersPicked = 0
    for i,number in enumerate(seq):
        prob = (k-numbersPicked)/(len(seq)-i)
        if random.random() < prob:
            yield number
            numbersPicked += 1

ধারণা এবং পরীক্ষার প্রমাণ যে সম্ভাবনাগুলি সঠিক :

২ ঘন্টা ধরে 1 ট্রিলিয়ন সিউডোর্যান্ডম নমুনা সহ সিমুলেটেড:

>>> Counter(
        tuple(orderedSampleWithoutReplacement([0,1,2,3], 2))
        for _ in range(10**9)
    )
Counter({
    (0, 3): 166680161, 
    (1, 2): 166672608, 
    (0, 2): 166669915, 
    (2, 3): 166667390, 
    (1, 3): 166660630, 
    (0, 1): 166649296
})

সম্ভাব্যতাগুলি সম্ভাব্যতাগুলি থেকে 1.0001 এর কম ফ্যাক্টর দ্বারা প্রকৃত সম্ভাবনাগুলি থেকে আলাদা করা হয়। এই পরীক্ষাটি আবার চালানোর ফলে ভিন্ন অর্ডার হয়েছে যার অর্থ এটি কোনও অর্ডারের দিকে পক্ষপাতদুষ্ট নয়। এর জন্য কম নমুনা নিয়ে পরীক্ষা চালানো [0,1,2,3,4], k=3এবং [0,1,2,3,4,5], k=4এর একই রকম ফলাফল had

সম্পাদনা করুন: কেন লোকেরা ভুল মন্তব্যে ভোট দিচ্ছেন বা উজ্জীবিত হতে ভয় করছেন তা নিশ্চিত নয় ... না, এই পদ্ধতিতে কোনও ভুল নেই। =)

(মন্তব্যগুলিতে ব্যবহারকারী তেগনের কাছ থেকে একটি দরকারী নোট: এটি যদি অজগর 2 হয় তবে আপনি যদি অতিরিক্ত স্থান সম্পর্কে সত্যই যত্নশীল হন তবে আপনি যথারীতি এক্সরেঞ্জ ব্যবহার করতে চাইবেন))

সম্পাদনা : প্রুফ: আকারের kজনসংখ্যার বাইরে একটি উপসেট বাছাইয়ের অভিন্ন বিতরণ (প্রতিস্থাপন ছাড়াই) বিবেচনা করে , আমরা একটি বামে একটি নির্বিচার বিন্দুতে একটি পার্টিশন বিবেচনা করতে পারি (0,1, ..., i-1) এবং 'ডান' (i, i + 1, ..., লেন (সিক)) প্রদত্ত যে আমরা বাম পরিচিত উপসেটটি থেকেছি, বাকিগুলি অবশ্যই ডান অজানা সাবসেটে একই ইউনিফর্ম বিতরণ থেকে আসতে হবে, যদিও প্যারামিটারগুলি এখন ভিন্ন। বিশেষত, সম্ভাবনা যেseqlen(seq)inumbersPickedseq[i] একটি নির্বাচিত উপাদান রয়েছে এমন হ'ল #remainingToChoose/#remainingToChooseFrom, বা(k-numbersPicked)/(len(seq)-i), তাই আমরা তা অনুকরণ এবং ফলাফল পুনরাবৃত্তি। (এটি অবশ্যই অবসান হতে হবে যদি # রিমেনিংটুচুজ == # রিটার্নিং টোচুজফ্রোম থেকে থাকে তবে সমস্ত অবশিষ্ট সম্ভাবনা ১ হয়)) এটি গতিশীলভাবে উত্পন্ন হওয়ার সম্ভাবনা গাছের মতো। মূলত আপনি পূর্ব পছন্দগুলির উপর কন্ডিশনিং দ্বারা অভিন্ন সম্ভাব্যতা বন্টন অনুকরণ করতে পারেন (আপনি সম্ভাব্য গাছটি বাড়ার সাথে সাথে আপনি বর্তমান শাখার সম্ভাবনাটি বেছে নেবেন যেমন এটি পূর্বের পাতার মতো একই রকম, যেমন পূর্বের পছন্দগুলিতে শর্তযুক্ত; এটি কাজ করবে কারণ এই সম্ভাবনাটি সমানভাবে এন / কে)।

সম্পাদনা : টিমোথি শিল্ডস জলাধার স্যাম্পলিংয়ের উল্লেখ করেছে , যা len(seq)অজানা (যেমন জেনারেটর এক্সপ্রেশন সহ) অজানা অবস্থায় এই পদ্ধতির সাধারণীকরণ । বিশেষত "অ্যালগরিদম আর" হিসাবে উল্লিখিত একটিটি যদি স্থান-স্থানে করা হয় তবে ও (এন) এবং ও (1) স্থান; এটি প্রথম এন উপাদান গ্রহণ এবং ধীরে ধীরে তাদের প্রতিস্থাপন জড়িত (একটি প্ররোচক প্রমাণ একটি ইঙ্গিতও দেওয়া হয়)। উইকিপিডিয়া পৃষ্ঠায় সন্ধানের জন্য দরকারী বিতরণযোগ্য রূপগুলি এবং জলাধার নমুনার বিবিধ রূপগুলিও রয়েছে।

সম্পাদনা করুন : এখানে আরও শব্দার্থিকভাবে সুস্পষ্ট পদ্ধতিতে কোড করার আরও একটি উপায়।

from __future__ import division
import random

def orderedSampleWithoutReplacement(seq, sampleSize):
    totalElems = len(seq)
    if not 0<=sampleSize<=totalElems:
        raise ValueError('Required that 0 <= sample_size <= population_size')

    picksRemaining = sampleSize
    for elemsSeen,element in enumerate(seq):
        elemsRemaining = totalElems - elemsSeen
        prob = picksRemaining/elemsRemaining
        if random.random() < prob:
            yield element
            picksRemaining -= 1

from collections import Counter         
Counter(
    tuple(orderedSampleWithoutReplacement([0,1,2,3], 2))
    for _ in range(10**5)

)


4
@pst: কোন অসুবিধা শুধু একটি speedup O(N)বরংO(N log(N))
ninjagecko

4
খুব সুন্দর, আমি ভাবছিলাম যে কীভাবে এই লিনিয়ার অ্যাপ্রোচটি করা যায়। এই সূত্রটিতে কি উইকিপিডিয়া পৃষ্ঠা রয়েছে? :)
জোচেন রিটেল

4
আমি অবাক হয়েছি যে এই উত্তরটির আরও বেশি অগ্রগতি নেই, এটি আসলে ব্যাখ্যা করে যে সমাধানটি কীভাবে কাজ করে (এবং আরও একটি সমাধান সরবরাহ করে!), প্রথম উত্তরটির বিপরীতে যা কেবল একটি লাইন স্নিপেট - কেন আমাকে বা কেন ধারণা দেয় না কিভাবে এটি কাজ করে।
ক্রেজি 2 বি

4
চমৎকার সমাধান নিনজেকেকো। যদি কেউ এটি লেখার আগ্রহী হয় তবে আপনার সমাধানের জন্য একটি দুর্দান্ত সূচক প্রমাণ রয়েছে।
নীল জি

4
চমৎকার সমাধান! from __future__ import divisionপাইথন ২ চালাচ্ছেন তাদের জন্য যুক্ত করতে ভুলবেন না ।
x অ্যাপল

7

হতে পারে আপনি কেবল সূচকগুলির নমুনা তৈরি করতে পারেন এবং তারপরে আপনার তালিকা থেকে আইটেমগুলি সংগ্রহ করতে পারেন।

randIndex = random.sample(range(len(mylist)), sample_size)
randIndex.sort()
rand = [mylist[i] for i in randIndex]

4

স্পষ্টতই random.sampleপাইথন ২.৩ এ প্রবর্তিত হয়েছিল

সুতরাং এর অধীনে সংস্করণের জন্য, আমরা শিফেল ব্যবহার করতে পারি (4 টি আইটেমের উদাহরণস্বরূপ):

myRange =  range(0,len(mylist)) 
shuffle(myRange)
coupons = [ bestCoupons[i] for i in sorted(myRange[:4]) ]

4
আপনি পাইথন ২.২ ব্যবহার করছেন ?! আপনার আপগ্রেড করা উচিত ... এটাই পুরানো।
ক্যাট্রিয়েল

4
ভাল, তার কি আমরা সার্ভারে আছে .. একটি সিস্টেম-ব্যাপী আপডেট উপার্জন অত্যধিক আমলাতন্ত্র হয়
Yochai Timmer

-2

এলোমেলোভাবে। নমুনা এটি বাস্তবায়ন।

>>> random.sample([1, 2, 3, 4, 5],  3)   # Three samples without replacement
[4, 1, 5]

9
আদেশ করা হয় না।
এস্ট্রিড
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.