Potřebuji vygenerovat náhodná čísla podle normálního rozdělení v intervalu $ (a, b) $. (Pracuji v R.)

Vím, že funkce rnorm(n,mean,sd) vygeneruje náhodná čísla po normálním rozdělení, ale jak v rámci toho nastavit limity intervalu? Jsou k dispozici nějaké konkrétní funkce R?

Komentáře

  • Proč to chcete dělat? Pokud je ‚ s ohraničen, nemůže to být ‚ normální. Co se snažíte dosáhnout?
  • x <- rnorm(n, mean, sd); x <- x[x > lower.limit & x < upper.limit]
  • @Hugh, že ‚ je skvělý … pokud vám ‚ nezáleží na tom, kolik náhodných hodnot získáte.

Odpovědět

Zní to, jako byste chtěli simulovat z zkrácené distribuce a ve vašem konkrétním příkladu , a zkrácený normální .

Existuje celá řada metod, některé jednoduché, jiné relativně účinný.

Na vašem normálním příkladu ilustruji některé přístupy.

  1. Zde je jedna velmi jednoduchá metoda pro generování jednoho po druhém (v nějakém druhu pseudokódu) ):

    $ \ tt {repeat} $ generovat $ x_i $ z N (mean, sd) $ \ tt {until} $ lower $ \ leq x_i \ leq $ vrchní

    zde zadejte popis obrázku

    Pokud je většina distribuce v mezích, je to docela rozumné, ale může to docela zpomalit, pokud téměř vždy generujete mimo limity.

    V R byste se mohli vyhnout smyčce one-at-a-time výpočtem oblasti v mezích a vygenerovat dostatek hodnot, o kterých si můžete být téměř jisti, že po vyhodení hodnoty mimo hranice jste stále měli tolik hodnot, kolik je potřeba.

  2. Můžete použít přijmout-odmítnout s nějakou vhodnou majorizační funkcí v daném intervalu (v některých případech bude být dost dobrý). Pokud by limity byly přiměřeně úzké vzhledem k s.d. ale nebyli jste daleko do ocasu, jednotná majorizace by fungovala dobře například s normálem.

    zde zadejte popis obrázku

  3. Pokud máte přiměřeně efektivní formát cdf a inverzní formát cdf (například pnorm a qnorm pro normální distribuce v R) můžete použít metodu inverzní-cdf popsanou v prvním odstavci simulační části stránky Wikipedie na zkráceném normálu . [Ve skutečnosti to je stejné jako vzít zkrácenou uniformu (zkrácenou na požadované kvantily, což ve skutečnosti nevyžaduje vůbec žádné odmítnutí, protože to je jen další uniforma) a použít na ni inverzní normální cdf. Upozorňujeme, že to může selhat, pokud jste daleko za ocasem.

    zde zadejte popis obrázku

  4. Existují i jiné přístupy; stejná stránka Wikipedie zmiňuje přizpůsobení metody ziggurat , která by měla fungovat pro různé distribuce.

stejný odkaz na Wikipedii zmiňuje dva konkrétní balíčky (oba na CRAN) s funkcemi pro generování zkrácených normálů:

Balíček MSM v R má funkci rtnorm, která počítá čerpání ze zkráceného normální. Balíček truncnorm v R má také funkce, které lze čerpat ze zkráceného normálu.


Když se podíváme kolem sebe, hodně z toho je pokryto odpověďmi na další otázky (ale ne přesně duplikáty, protože tato otázka je obecnější než jen zkrácená normální) … viz další diskuse v

a. Tato odpověď

b. Xi „an“ s odpověď zde , která obsahuje odkaz na jeho článek arXiv (spolu s dalšími užitečnými odpověďmi).

Odpověď

Rychlým a špinavým přístupem je použití pravidla 68-95-99.7 .

Při normálním rozdělení spadá 99,7% hodnot do 3 standardních odchylek od průměru. Pokud tedy nastavíte střední hodnotu na střed požadované minimální hodnoty a maximální hodnoty a nastavíte směrodatnou odchylku na 1/3 střední hodnoty, získáte (většinou) hodnoty, které spadají do požadovaného intervalu. Potom můžete jen uklidit zbytek.

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) 

Nedávno jsem čelil stejnému problému a snažil jsem se vygenerovat náhodné hodnocení studentů pro testovací data. Ve výše uvedeném kódu jsem použil pmax a pmin k nahrazení mezních hodnot minimálními nebo maximálními mezními hodnotami hodnota.To funguje pro můj účel, protože generuji poměrně malé množství dat, ale pro větší množství vám to dá znatelné hrboly na min. A max. Hodnotách. Takže podle vašich účelů může být lepší tyto hodnoty zahodit a nahradit je. s NA s nebo je „přetočit“, dokud se nedostanou do hranic.

Komentáře

  • Proč se s tím obtěžovat? Generovat normální náhodná čísla a zrušit ta, která potřebují zkrácení, je tak jednoduché, že není nutné ‚ to komplikovat, pokud požadované zkrácení nedosahuje téměř 100% plochy hustoty.
  • Možná si ‚ misinterpretuji původní otázku. Na tuto otázku jsem narazil, když jsem se snažil přijít na to, jak dosáhnout programovacího úkolu nesouvisejícího přímo se statistikami v R, a ‚ jsem si až teď všiml, že tato stránka je statistická výměna zásobníku , nikoli programová výměna zásobníku. 🙂 V mém případě jsem chtěl vygenerovat konkrétní množství náhodných celých čísel s hodnotami od 0 do 100 a chtěl jsem, aby vygenerované hodnoty padly na pěknou křivku zvonu v tomto rozsahu. Od psaní tohoto článku jsem si ‚ uvědomil, že sample(x=min:max, prob=dnorm(...)) je možná snadnější způsob, jak to udělat.
  • @Glen_b Aaron Wells zmiňuje sample(x=min:max, prob=dnorm(...)), což se zdá být o něco kratší než vaše odpověď.
  • Pamatujte však, že trik sample() je užitečný pouze pokud ‚ zkoušíte vybrat náhodná celá čísla nebo jinou sadu samostatných předdefinovaných hodnot.

Odpovědět

Žádná z odpovědí zde neposkytuje efektivní metodu generování zkrácených normálních proměnných, která nezahrnuje odmítnutí libovolně velkých počty vygenerovaných hodnot. Pokud chcete generovat hodnoty ze zkráceného normálního rozdělení se zadanými dolními a horními mezemi $ a < b $ , toto lze provést — bez odmítnutí — generováním jednotných kvantilů v rozsahu kvantilů povoleném zkrácením a použitím vzorkování inverzní transformace k získání odpovídajících normálních hodnot .

Nechť $ \ Phi $ označuje CDF standardní normální distribuce. Chceme vygenerovat $ X_1, …, X_N $ ze zkrácené normální distribuce (se středním parametrem $ \ mu $ a parametr odchylky $ \ sigma ^ 2 $ ) $ ^ \ dagger $ s nižšími a horní hranice zkrácení $ a < b $ . To lze provést následovně:

$$ 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]. $$

Neexistuje žádná vestavěná funkce pro generované hodnoty ze zkrácené distribuce, ale je triviální programovat tuto metodu pomocí běžné funkce pro generování náhodných proměnných. Zde je jednoduchá R funkce rtruncnorm, která tuto metodu implementuje do několika řádků kódu.

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

Toto je vektorizovaná funkce, která vygeneruje N IID náhodné proměnné ze zkrácené normální distribuce. Stejnou metodou by bylo snadné programovat funkce pro jiné zkrácené distribuce. Také by nebylo příliš obtížné naprogramovat přidružené hustotní a kvantilové funkce pro zkrácenou distribuci.


$ ^ \ dagger $ Pamatujte, že zkrácení mění průměr a rozptyl distribuce, takže $ \ mu $ a $ \ sigma ^ 2 $ nejsou ne průměr a rozptyl zkrácené distribuce.

Odpověď

Mně fungovaly tři způsoby:

  1. using sample () with rnorm ():

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

  2. pomocí balíčku msm a funkce rtnorm:

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

  3. pomocí rnorm () a určení dolní a horní hranice, jak zveřejnil Hugh výše:

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

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *