Am nevoie să generez numere aleatorii după distribuția normală în intervalul $ (a, b) $. (Lucrez în R.)

Știu că funcția rnorm(n,mean,sd) va genera numere aleatorii după distribuție normală, dar cum să stabilim limitele intervalului în cadrul acestuia? Există anumite funcții R disponibile pentru acest lucru?

Comentarii

  • De ce doriți să faceți acest lucru? Dacă ‘ este delimitat, atunci ‘ nu poate fi cu adevărat normal. Ce încercați să realizați?
  • x <- rnorm(n, mean, sd); x <- x[x > lower.limit & x < upper.limit]
  • @Hugh că ‘ este grozav … atâta timp cât nu îți pasă ‘ de câte valori aleatorii primești.

Răspunde

Sună de parcă vrei să simulezi dintr-o distribuție trunchiată și în exemplul tău specific , a normal trunchiat .

Există o varietate de metode pentru a face acest lucru, unele simple, altele relativ eficient.

Voi ilustra câteva abordări ale exemplului dvs. normal.

  1. Aici este o metodă foarte simplă pentru a genera una câte una (într-un fel de pseudocod) ):

    $ \ tt {repeat} $ genera $ x_i $ din N (mean, sd) $ \ tt {until} $ inferior $ \ leq x_i \ leq $ upper

    introduceți descrierea imaginii aici

    Dacă cea mai mare parte a distribuției se încadrează în limite, acest lucru este destul de rezonabil, dar poate deveni destul de lent dacă aproape întotdeauna generați în afara limitelor.

    În R ați putea evita bucla una câte una prin calcularea zonei dintre limite și puteți genera suficiente valori încât să puteți fi aproape siguri că după ce ați aruncat valorile în afara limitelor aveați încă câte valori era nevoie.

  2. Puteți utiliza accept-respingere cu o funcție de majorare adecvată pe interval (în unele cazuri uniformă va fii suficient de bun). Dacă limitele ar fi în mod rezonabil înguste în raport cu s.d. dar nu erați prea departe în coadă, o majorare uniformă ar funcționa bine cu normalul, de exemplu.

    introduceți descrierea imaginii aici

  3. Dacă aveți un cdf invers și cdf invers (cum ar fi pnorm și qnorm distribuție normală în R) puteți utiliza metoda inversă-cdf descrisă în primul paragraf al secțiunii de simulare a pagina Wikipedia pe normalul trunchiat . [De fapt aceasta este la fel ca și luarea unui uniform trunchiat (trunchiat la cuantilele necesare, care de fapt nu necesită deloc respingeri, deoarece acesta este doar o altă uniformă) și se aplică inversul cdf normal. Rețineți că acest lucru poate eșua dacă „sunteți departe în coadă]

    introduceți descrierea imaginii aici

  4. Există alte abordări; aceeași pagină Wikipedia menționează adaptarea metodei ziggurat , care ar trebui să funcționeze pentru o varietate de distribuții.

același link Wikipedia menționează două pachete specifice (ambele pe CRAN) cu funcții de generare a normelor trunchiate:

Pachetul MSM din R are o funcție, rtnorm, care calculează extragerile dintr-un element trunchiat normal. Pachetul truncnorm din R are și funcții de trasat dintr-un normal trunchiat.


Privind în jur, multe dintre acestea sunt acoperite de răspunsuri la alte întrebări (dar nu exact duplicate, deoarece această întrebare este mai generală decât simpla normală trunchiată) … vezi discuții suplimentare în

a. Acest răspuns

b. Răspunsul Xi „an” aici , care are un link către lucrarea sa arXiv (împreună cu alte răspunsuri care merită).

Răspuns

Abordarea rapidă și murdară este de a utiliza regula 68-95-99.7 .

Într-o distribuție normală, 99,7% din valori se încadrează în 3 abateri standard ale mediei. Deci, dacă vă setați media la mijlocul valorii minime și a valorii maxime dorite și setați abaterea standard la 1/3 din media dvs., obțineți (în majoritate) valori care se încadrează în intervalul dorit. Apoi, puteți purifica restul.

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) 

Am întâmpinat recent aceeași problemă, încercând să generez note aleatoare ale elevilor pentru datele testelor. În codul de mai sus, am „folosit pmax și pmin pentru a înlocui valorile în afara limitelor cu min sau max în limite valoare.Acest lucru funcționează pentru scopul meu, deoarece generez cantități destul de mici de date, dar pentru cantități mai mari vă va oferi valori semnificative la valorile minime și maxime. Deci, în funcție de scopurile dvs., poate fi mai bine să le aruncați, înlocuiți-le cu NA s sau „re-roll” până când acestea sunt „în limitele lor.

Comentarii

  • De ce să te deranjezi să faci asta? Este atât de simplu să generați numere aleatorii normale și să le eliminați pe cele care au nevoie de trunchiere, încât nu este necesar să fiți complicat în acest sens, cu excepția cazului în care trunchierea dorită este aproape de 100% din suprafață. densității.
  • Poate că ‘ interpretez greșit întrebarea inițială. Am întâlnit această întrebare în timp ce încercam să aflu cum să realizez o sarcină de programare care nu este direct legată de statistici în R și am ‘ abia acum am observat că această pagină este o stivă de schimb de statistici , nu un stackexchange de programare. 🙂 În cazul meu, am vrut să generez o cantitate specifică de numere întregi aleatorii, cu valori cuprinse între 0 și 100 și am vrut ca valorile generate să cadă pe o curbă frumoasă de clopot în acea gamă. De când am scris acest lucru, am ‘ am realizat că sample(x=min:max, prob=dnorm(...)) este poate o modalitate mai ușoară de a face acest lucru.
  • @Glen_b Aaron Wells menționează sample(x=min:max, prob=dnorm(...)) care pare puțin mai scurt decât răspunsul dvs.
  • Dar rețineți că trucul sample() este util doar dacă ‘ încercați să alegeți numere întregi aleatorii sau un alt set de valori discrete, predefinite.

Răspuns

Niciunul dintre răspunsurile de aici nu oferă o metodă eficientă de generare a trunchiat variabile normale care nu implică respingerea unor mărimi arbitrare mari numere de valori generate. Dacă doriți să generați valori dintr-o distribuție normală trunchiată, cu limite inferioare și superioare specificate $ a < b $ , aceasta se poate face — fără respingere — generând cuantile uniforme peste intervalul cuantil permis de trunchiere și utilizând eșantionare inversă a transformării pentru a obține valorile normale corespunzătoare .

$ \ Phi $ să indice CDF-ul distribuției normale standard. Vrem să generăm $ X_1, …, X_N $ dintr-o distribuție normală trunchiată (cu parametrul mediu $ \ mu $ și parametrul de varianță $ \ sigma ^ 2 $ ) $ ^ \ dagger $ cu mai mici și limite superioare de trunchiere $ a < b $ . Acest lucru se poate face după cum urmează:

$$ X_i = \ mu + \ sigma \ cdot \ Phi ^ {- 1} (U_i) \ quad \ quad \ quad U_1, …, U_N \ sim \ text {IID U} \ Big [\ Phi \ Big (\ frac {a- \ mu} {\ sigma} \ Big), \ Phi \ Big (\ frac {b- \ mu} {\ sigma} \ Big) \ Big]. $$

Nu există nicio funcție încorporată pentru valorile generate din distribuția trunchiată, dar este banal să programați această metodă folosind funcții obișnuite pentru generarea de variabile aleatorii. Iată o funcție simplă R rtruncnorm care implementează această metodă în câteva linii de cod.

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); } 

Aceasta este o funcție vectorizată care va genera N variabile aleatorii IID din distribuția normală trunchiată. Ar fi ușor să programați funcții pentru alte distribuții trunchiate prin aceeași metodă. De asemenea, nu ar fi prea dificil să programăm funcțiile de densitate și cuantilă asociate pentru distribuția trunchiată.


$ ^ \ dagger $ Rețineți că trunchierea modifică media și varianța distribuției, deci $ \ mu $ și $ \ sigma ^ 2 $ sunt nu media și varianța distribuției trunchiate.

Răspuns

Trei moduri au funcționat pentru mine:

  1. folosind sample () cu rnorm ():

    sample(x=min:max, replace= TRUE, rnorm(n, mean))

  2. utilizând pachetul msm și funcția rtnorm:

    rtnorm(n, mean, lower=min, upper=max)

  3. folosind rnorm () și specificând limitele inferioară și superioară, așa cum a postat Hugh mai sus:

    sample <- rnorm(n, mean=mean); sample <- sample[x > min & x < max]

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *