Hasilkan angka acak mengikuti distribusi dalam interval

17

Saya perlu membuat angka acak mengikuti distribusi normal dalam interval . (Saya bekerja di R.)(a,b)

Saya tahu fungsi ini rnorm(n,mean,sd)akan menghasilkan angka acak mengikuti distribusi normal, tetapi bagaimana cara menetapkan batas interval di dalamnya? Apakah ada fungsi R tertentu yang tersedia untuk itu?

dvs
sumber
Mengapa Anda ingin melakukan ini? Jika dibatasi maka itu tidak bisa benar-benar normal. Apa yang ingin Anda capai?
gung - Reinstate Monica
x <- rnorm(n, mean, sd); x <- x[x > lower.limit & x < upper.limit]
Hugh
3
@Huh itu bagus ... selama Anda tidak peduli berapa banyak nilai acak yang Anda dapatkan.
Glen_b -Reinstate Monica

Jawaban:

31

Sepertinya Anda ingin mensimulasikan dari distribusi terpotong , dan dalam contoh spesifik Anda, normal terpotong .

Ada berbagai metode untuk melakukannya, ada yang sederhana, ada juga yang relatif efisien.

Saya akan menggambarkan beberapa pendekatan pada contoh normal Anda.

  1. Inilah satu metode yang sangat sederhana untuk menghasilkan satu per satu (dalam beberapa jenis kodesemu):

    repeat menghasilkan dari N (rata-rata, sd) lebih rendah atasxiuntilxi

    masukkan deskripsi gambar di sini

    Jika sebagian besar distribusi berada dalam batas, ini cukup masuk akal tetapi bisa menjadi sangat lambat jika Anda hampir selalu menghasilkan di luar batas.

    Di R, Anda dapat menghindari loop satu per satu dengan menghitung area di dalam batas dan menghasilkan nilai yang cukup sehingga Anda bisa hampir yakin bahwa setelah membuang nilai di luar batas, Anda masih memiliki nilai sebanyak yang diperlukan.

  2. Anda dapat menggunakan accept-reject dengan beberapa fungsi mayor yang sesuai selama interval (dalam beberapa kasus seragam akan cukup baik). Jika batas-batasnya cukup sempit relatif terhadap sd tetapi Anda tidak jauh ke ekor, jurusan seragam akan bekerja dengan normal, misalnya.

    masukkan deskripsi gambar di sini

  3. Jika Anda memiliki cdf efisien dan invers cdf (seperti pnormdan qnormuntuk distribusi normal dalam R), Anda dapat menggunakan metode invers-cdf yang dijelaskan dalam paragraf pertama dari bagian simulasi halaman Wikipedia pada terpotong normal . [Akibatnya ini sama dengan mengambil seragam terpotong (terpotong pada kuantil yang diperlukan, yang sebenarnya tidak memerlukan penolakan sama sekali, karena itu hanya seragam lain) dan menerapkan cdf normal terbalik untuk itu. Perhatikan bahwa ini bisa gagal jika Anda jauh ke ekor]

    masukkan deskripsi gambar di sini

  4. Ada beberapa pendekatan lain; halaman Wikipedia yang sama menyebutkan mengadaptasi metode ziggurat , yang seharusnya bisa digunakan untuk berbagai distribusi.

The Link Wikipedia yang sama menyebutkan dua paket khusus (baik di CRAN) dengan fungsi untuk menghasilkan normals terpotong:

The MSMpaket di R memiliki fungsi, rtnorm, yang menghitung menarik dari normal terpotong. The truncnormpaket di R juga memiliki fungsi untuk menarik dari sebuah terpotong normal.


Melihat sekeliling, banyak dari ini tercakup dalam jawaban atas pertanyaan lain (tetapi tidak persis duplikat karena pertanyaan ini lebih umum daripada hanya yang terpotong normal) ... lihat diskusi tambahan di

Sebuah. Jawaban ini

b. Jawaban Xi'an di sini , yang memiliki tautan ke makalah arXivnya (bersama dengan beberapa tanggapan berharga lainnya).

Glen_b -Reinstate Monica
sumber
2

Pendekatan cepat dan kotor adalah dengan menggunakan aturan 68-95-99.7 .

Dalam distribusi normal, 99,7% dari nilai berada dalam 3 standar deviasi dari rata-rata. Jadi, jika Anda menetapkan nilai tengah ke nilai minimum yang Anda inginkan dan nilai maksimum, dan menetapkan standar deviasi Anda menjadi 1/3 dari nilai rata-rata Anda, Anda mendapatkan (sebagian besar) nilai yang berada dalam interval yang diinginkan. Maka Anda bisa membersihkan sisanya.

minVal <- 0
maxVal <- 100
mn <- (maxVal - minVal)/2
# Generate numbers (mostly) from min to max
x <- rnorm(count, mean = mn, sd = mn/3)
# Do something about the out-of-bounds generated values
x <- pmax(minVal, x)
x <- pmin(maxVal, x)

Baru-baru ini saya menghadapi masalah yang sama, mencoba menghasilkan nilai siswa acak untuk data tes. Dalam kode di atas, saya telah menggunakan pmaxdan pminuntuk mengganti nilai di luar batas dengan nilai min atau max di dalam batas. Ini berfungsi untuk tujuan saya, karena saya menghasilkan jumlah data yang cukup kecil, tetapi untuk jumlah yang lebih besar itu akan memberi Anda benjolan yang terlihat pada nilai minimum dan maksimum. Jadi, tergantung pada tujuan Anda, mungkin lebih baik membuang nilai-nilai itu, menggantinya dengan NAs, atau "menggulung kembali" nilai-nilai itu sampai nilai-nilai tersebut berada dalam batas.

Aaron Wells
sumber
Kenapa repot-repot melakukan ini? Sangat sederhana untuk menghasilkan angka acak normal dan menjatuhkan angka yang perlu pemotongan sehingga tidak perlu rumit tentang hal itu kecuali pemotongan yang diinginkan mendekati 100% dari luas kepadatan.
Carl
2
Mungkin saya salah menafsirkan pertanyaan aslinya. Saya menemukan pertanyaan ini ketika mencoba mencari cara untuk mencapai tugas pemrograman yang tidak berhubungan langsung dengan statistik di R, dan saya baru sekarang menyadari bahwa halaman ini adalah statistik stackexchange, bukan pemrograman stackexchange. :) Dalam kasus saya, saya ingin menghasilkan jumlah tertentu dari bilangan bulat acak, dengan nilai mulai dari 0 hingga 100, dan saya ingin nilai yang dihasilkan jatuh pada kurva lonceng yang bagus di rentang itu. Sejak menulis ini, saya menyadari bahwa sample(x=min:max, prob=dnorm(...))mungkin itu cara yang lebih mudah untuk melakukannya.
Aaron Wells
@ Glen_b Aaron Wells menyebutkan sample(x=min:max, prob=dnorm(...))yang tampaknya sedikit lebih pendek dari jawaban Anda.
Carl
Tetapi perhatikan bahwa sample()trik ini hanya berguna jika Anda mencoba untuk memilih bilangan bulat acak, atau nilai diskrit lain yang telah ditentukan sebelumnya.
Aaron Wells
1

a<b

ΦX1,...,XNμσ2a<b

Xi=μ+σΦ1(Ui)U1,...,UNIID U[Φ(aμσ),Φ(bμσ)].

Tidak ada fungsi inbuilt untuk nilai yang dihasilkan dari distribusi terpotong, tetapi sepele untuk memprogram metode ini menggunakan fungsi biasa untuk menghasilkan variabel acak. Berikut adalah Rfungsi sederhana rtruncnormyang mengimplementasikan metode ini dalam beberapa baris kode.

rtruncnorm <- function(N, mean = 0, sd = 1, a = -Inf, b = Inf) {
  if (a > b) stop('Error: Truncation range is empty');
  U <- runif(N, pnorm(a, mean, sd), pnorm(b, mean, sd));
  qnorm(U, mean, sd); }

Ini adalah fungsi vectorised yang akan menghasilkan Nvariabel acak IID dari distribusi normal terpotong. Akan mudah untuk memprogram fungsi untuk distribusi terpotong lainnya melalui metode yang sama. Juga tidak akan terlalu sulit untuk memprogram kerapatan terkait dan fungsi kuantil untuk distribusi terpotong.


μσ2

Pasang kembali Monica
sumber