ตัวเลขสุ่มที่ไม่ซ้ำกันเป็นตัวเลข


92

ฉันจะสร้างตัวเลขสุ่มที่ไม่ซ้ำซากเป็นตัวเลขได้อย่างไร

list = np.random.random_integers(20,size=(10))

คำว่า "ไม่ซ้ำซาก" หมายความว่าอย่างไร ลำดับของตัวเลขสุ่มไม่เคยเกิดซ้ำ? เป็นไปไม่ได้เนื่องจากสถานะของตัวสร้างตัวเลขสุ่มต้องพอดีกับหน่วยความจำ จำกัด ของคอมพิวเตอร์ หรือคุณหมายความว่าไม่มีเลขตัวเดียวเกิดขึ้นสองครั้ง?
Sven Marnach

5
ไม่ซ้ำซากหมายความว่าคุณมีรายการที่ไม่มีรายการซ้ำ
พหุนาม

2
บางทีคุณอาจต้องการการเปลี่ยนแปลงแบบสุ่ม? docs.scipy.org/doc/numpy/reference/generated/…
cyborg

คำตอบ:


112

numpy.random.Generator.choiceเสนอreplaceอาร์กิวเมนต์ให้กับตัวอย่างโดยไม่ต้องเปลี่ยน:

from numpy.random import default_rng

rng = default_rng()
numbers = rng.choice(20, size=10, replace=False)

หากคุณใช้ NumPy ก่อน 1.17 โดยไม่มีGeneratorAPI คุณสามารถใช้random.sample()จากไลบรารีมาตรฐาน:

print(random.sample(range(20), 10))

คุณยังสามารถใช้numpy.random.shuffle()และหั่นบาง ๆ ได้ แต่จะมีประสิทธิภาพน้อยลง:

a = numpy.arange(20)
numpy.random.shuffle(a)
print a[:10]

นอกจากนี้ยังมีreplaceอาร์กิวเมนต์ในnumpy.random.choiceฟังก์ชันเดิมแต่อาร์กิวเมนต์นี้ถูกนำไปใช้อย่างไม่มีประสิทธิภาพและปล่อยให้ไม่มีประสิทธิภาพเนื่องจากการรับประกันความเสถียรของสตรีมตัวเลขแบบสุ่มดังนั้นจึงไม่แนะนำให้ใช้ (โดยทั่วไปจะเป็นการสับเปลี่ยนและแบ่งชิ้นส่วนภายใน)


1
พิมพ์แบบสุ่มตัวอย่าง (ช่วง (20), 10) ใช้ไม่ได้กับ python 2.6 ?!
Academia

ปัญหาเกิดจากการกำหนดค่า Pydev ที่ไม่ดี Thks
Academia

1
จะเป็นอย่างไรถ้า n ของฉันไม่ใช่ 20 แต่เหมือน 1000000 แต่ฉันต้องการตัวเลขที่ไม่ซ้ำกันเพียง 10 ตัวจากนั้นจะมีวิธีการที่มีประสิทธิภาพหน่วยความจำมากกว่านี้หรือไม่?
mrgloom

2
@mrgloom ใน Python 3 random.sample(range(n), 10))จะมีประสิทธิภาพแม้ว่าจะมีขนาดใหญ่มากnก็ตามเนื่องจากrangeออบเจ็กต์เป็นเพียง Wrapper ขนาดเล็กที่จัดเก็บค่าเริ่มต้นหยุดและขั้นตอน แต่จะไม่สร้างรายการจำนวนเต็มทั้งหมด ใน Python 2 คุณสามารถแทนที่rangeด้วยxrangeเพื่อให้ได้พฤติกรรมที่คล้ายกัน
Sven Marnach

110

ฉันคิดว่าใช้numpy.random.sampleไม่ได้แล้วตอนนี้ นี่คือวิธีของฉัน:

import numpy as np
np.random.choice(range(20), 10, replace=False)

26
แทนที่จะrange(n)(หรือarange(n)) เป็นอาร์กิวเมนต์แรกของchoiceมันเทียบเท่ากับเพียงแค่ผ่านเช่นn choice(20, 10, replace=False)
Josh Bode

1
โปรดทราบว่าnp.random.choice(a, size, replace=False)ช้ามากสำหรับขนาดใหญ่a- บนเครื่องของฉันประมาณ 30 ms สำหรับ a = 1M
Matthew Rahtz

3
เพื่อหลีกเลี่ยงปัญหาด้านเวลาและหน่วยความจำสำหรับการnใช้งานขนาดใหญ่มากnumpy.random.Generator.choice(เริ่มต้นด้วย numpy v1.17)
benbo

1
ข้อเสียเปรียบหลักที่ฉันเห็นคือ np.random.choice ไม่มีพารามิเตอร์แกน -> สำหรับอาร์เรย์ 1d เท่านั้น
Moosefeather

3

หลายปีต่อมามีเวลาในการเลือก 40000 จาก 10,000 ^ 2 (Numpy 1.8.1, imac 2.7 GHz):

import random
import numpy as np

n = 10000
k = 4
np.random.seed( 0 )

%timeit np.random.choice( n**2, k * n, replace=True )  # 536 µs ± 1.58 µs
%timeit np.random.choice( n**2, k * n, replace=False ) # 6.1 s ± 9.91 ms

# https://docs.scipy.org/doc/numpy/reference/random/index.html
randomstate = np.random.default_rng( 0 )
%timeit randomstate.choice( n**2, k * n, replace=False, shuffle=False )  # 766 µs ± 2.18 µs
%timeit randomstate.choice( n**2, k * n, replace=False, shuffle=True )   # 1.05 ms ± 1.41 µs

%timeit random.sample( range( n**2 ), k * n )          # 47.3 ms ± 134 µs

(ทำไมต้องเลือก 40000 จาก 10,000 ^ 2 ในการสร้าง เมทริกซ์scipy.sparse.randomขนาดใหญ่ - การใช้ scipy 1.4.1 np.random.choice( replace=False )slooooow)

เคล็ดลับของหมวกสำหรับคนทั่วไป


1

คุณสามารถรับสิ่งนี้ได้โดยการจัดเรียงเช่นกัน:

random_numbers = np.random.random([num_samples, max_int])
samples = np.argsort(random_numbers, axis=1)

0

สามารถใช้การแปลงรายการชุด Python ได้ 10 หมายเลขที่ไม่ซ้ำกันระหว่าง 0 ถึง 20 สามารถรับได้ดังนี้:

import numpy as np
import random
unique_numbers=set()
while(len(unique_numbers)<10):
    unique_numbers.add(np.random.randint(0,20))

unique_numbers=list(unique_numbers)
random.shuffle(unique_numbers)
print(unique_numbers)

-3

เพียงสร้างอาร์เรย์ที่มีช่วงของตัวเลขที่ต้องการจากนั้นสับเปลี่ยนโดยการสลับสุ่มซ้ำ ๆ กับองค์ประกอบที่ 0 ในอาร์เรย์ สิ่งนี้จะสร้างลำดับแบบสุ่มที่ไม่มีค่าซ้ำกัน


2
ทรัพย์สินของสุ่มลำดับที่เกิดขึ้นก็คือว่ามันไม่ได้เป็นแบบสุ่มโดยเฉพาะอย่างยิ่ง
Sven Marnach

@SvenMarnach - สำหรับจุดประสงค์ส่วนใหญ่มันสุ่มเพียงพอ เขาสามารถใช้วิธีสุ่มสองครั้งได้หากต้องการสุ่มมากขึ้น
พหุนาม

นี่ไม่มีจุดหมาย OP สามารถใช้การเรียกไลบรารีเพื่อดำเนินการได้อย่างถูกต้อง ใช้งานง่ายกว่าทำงานเร็วกว่าและอ่านง่ายกว่าเวอร์ชันที่กำหนดเอง ฉันคิดไม่ออกว่าทำไมฉันจึงควรใช้อัลกอริทึมที่ไม่ถูกต้องเพียงเพราะมันน่าจะ "สุ่มเพียงพอ" เมื่อใช้อัลกอริทึมที่ถูกต้องจะไม่มีผลเสียใด ๆ
Sven Marnach

@SvenMarnach - พอใช้. ฉันไม่รู้ว่าเป็นอะไรดังนั้นฉันแค่เสนอวิธีแก้ปัญหาที่เป็นไปได้
พหุนาม
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.