Saya punya file dengan beberapa probabilitas untuk nilai yang berbeda, misalnya:
1 0.1
2 0.05
3 0.05
4 0.2
5 0.4
6 0.2
Saya ingin menghasilkan angka acak menggunakan distribusi ini. Apakah ada modul yang menangani hal ini? Cukup mudah untuk membuat kode sendiri (membangun fungsi kepadatan kumulatif, menghasilkan nilai acak [0,1] dan memilih nilai yang sesuai) tetapi sepertinya ini harus menjadi masalah umum dan mungkin seseorang telah membuat fungsi / modul untuk Itu.
Saya memerlukan ini karena saya ingin membuat daftar ulang tahun (yang tidak mengikuti distribusi apa pun di random
modul standar ).
random.choice()
? Anda membangun daftar master dengan jumlah kemunculan yang tepat dan memilih satu. Ini adalah pertanyaan rangkap, tentu saja.Jawaban:
scipy.stats.rv_discrete
mungkin apa yang Anda inginkan. Anda dapat menyediakan probabilitas Anda melaluivalues
parameter. Anda kemudian dapat menggunakanrvs()
metode objek distribusi untuk menghasilkan angka acak.Seperti yang ditunjukkan oleh Eugene Pakhomov di komentar, Anda juga dapat meneruskan
p
parameter kata kunci kenumpy.random.choice()
, misalnyaJika Anda menggunakan Python 3.6 atau lebih tinggi, Anda bisa menggunakan
random.choices()
dari pustaka standar - lihat jawabannya oleh Mark Dickinson .sumber
numpy.random.choice()
hampir 20 kali lebih cepat.numpy.random.choice(numpy.arange(1, 7), p=[0.1, 0.05, 0.05, 0.2, 0.4, 0.2])
Sejak Python 3.6, ada solusi untuk ini di perpustakaan standar Python, yaitu
random.choices
.Contoh penggunaan: mari atur populasi dan timbangan yang cocok dengan yang ada di pertanyaan OP:
Sekarang
choices(population, weights)
menghasilkan satu sampel:Argumen opsional hanya kata kunci
k
memungkinkan seseorang untuk meminta lebih dari satu sampel sekaligus. Ini berharga karena ada beberapa pekerjaan persiapan yangrandom.choices
harus dilakukan setiap kali dipanggil, sebelum menghasilkan sampel apa pun; dengan menghasilkan banyak sampel sekaligus, kita hanya perlu melakukan pekerjaan persiapan itu sekali saja. Di sini kami menghasilkan sejuta sampel, dan digunakancollections.Counter
untuk memeriksa apakah distribusi yang kami dapatkan kurang lebih sama dengan bobot yang kami berikan.sumber
Keuntungan membuat daftar menggunakan CDF adalah Anda dapat menggunakan pencarian biner. Meskipun Anda membutuhkan O (n) waktu dan ruang untuk preproses, Anda bisa mendapatkan angka k dalam O (k log n). Karena daftar Python normal tidak efisien, Anda dapat menggunakan
array
modul.Jika Anda bersikeras pada ruang konstan, Anda dapat melakukan hal berikut; O (n) waktu, O (1) ruang.
sumber
l[-1]
mengembalikan elemen terakhir dari daftar?Mungkin agak terlambat. Tapi Anda bisa menggunakan
numpy.random.choice()
, melewatip
parameter:sumber
random.choice()
- lihat komentar.numpy.random.choice()
sama sekali berbeda darirandom.choice()
dan mendukung distribusi probabilitas.(Oke, saya tahu Anda meminta psikiater, tetapi mungkin solusi buatan sendiri itu tidak cukup ringkas untuk keinginan Anda. :-)
Saya pseudo-confirm bahwa ini berfungsi dengan melihat keluaran ekspresi ini:
sumber
i
bukan objek.Saya menulis solusi untuk menggambar sampel acak dari distribusi kontinu kustom .
Saya membutuhkan ini untuk kasus penggunaan yang serupa dengan milik Anda (yaitu menghasilkan tanggal acak dengan distribusi probabilitas yang diberikan).
Anda hanya perlu funtion
random_custDist
dan garissamples=random_custDist(x0,x1,custDist=custDist,size=1000)
. Sisanya adalah dekorasi ^^.Kinerja solusi ini pasti dapat ditingkatkan, tetapi saya lebih suka keterbacaan.
sumber
Buat daftar barang, berdasarkan pada
weights
:Optimalisasi mungkin untuk menormalkan jumlah dengan pembagi umum terbesar, untuk membuat daftar target lebih kecil.
Juga, ini mungkin menarik.
sumber
Jawaban lain, mungkin lebih cepat :)
sumber
Verifikasi:
sumber
berdasarkan solusi lain, Anda menghasilkan distribusi akumulatif (sebagai bilangan bulat atau mengapung apa pun yang Anda suka), maka Anda dapat menggunakan dua bagian untuk membuatnya cepat
ini adalah contoh sederhana (saya menggunakan bilangan bulat di sini)
itu
get_cdf
fungsi akan mengubahnya dari 20, 60, 10, 10 menjadi 20, 20 + 60, 20 + 60 + 10, 20 + 60 + 10 + 10sekarang kita memilih nomor acak hingga 20 + 60 + 10 + 10 menggunakan
random.randint
maka kita menggunakan dua bagian untuk mendapatkan nilai aktual dengan cara cepatsumber
Anda mungkin ingin melihat distribusi sampling NumPy Random
sumber
Tidak satu pun dari jawaban ini yang jelas atau sederhana.
Ini adalah metode yang jelas dan sederhana yang dijamin akan berhasil.
akumulasi_normalisasi_probabilitas mengambil kamus
p
yang memetakan simbol untuk probabilitas ATAU frekuensi. Ini menghasilkan daftar tuple yang dapat digunakan untuk melakukan seleksi.Hasil:
Mengapa ini berhasil?
Langkah akumulasi mengubah setiap simbol menjadi interval antara dirinya dan probabilitas atau frekuensi simbol sebelumnya (atau 0 dalam kasus simbol pertama). Interval ini dapat digunakan untuk memilih dari (dan dengan demikian sampel distribusi yang disediakan) dengan hanya melangkah melalui daftar sampai angka acak dalam interval 0,0 -> 1,0 (disiapkan sebelumnya) kurang atau sama dengan titik akhir interval simbol saat ini.
The normalisasi melepaskan kita dari kebutuhan untuk memastikan semuanya jumlah untuk beberapa nilai. Setelah normalisasi, "vektor" probabilitas berjumlah 1,0.
The sisa kode untuk seleksi dan menghasilkan sampel sewenang-wenang panjang dari distribusi di bawah ini:
Penggunaan:
sumber
Inilah cara yang lebih efektif untuk melakukan ini:
Panggil saja fungsi berikut dengan array 'bobot' Anda (dengan asumsi indeks sebagai item yang sesuai) dan no. sampel yang dibutuhkan. Fungsi ini dapat dengan mudah dimodifikasi untuk menangani pasangan yang dipesan.
Mengembalikan indeks (atau item) yang diambil / dipilih (dengan penggantian) menggunakan probabilitas masing-masing:
Catatan singkat tentang konsep yang digunakan dalam loop sementara. Kami mengurangi berat item saat ini dari beta kumulatif, yang merupakan nilai kumulatif yang dibangun secara seragam secara acak, dan menambah indeks saat ini untuk menemukan item, berat yang cocok dengan nilai beta.
sumber