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
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.
-
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í
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.
-
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.
-
Pokud máte přiměřeně efektivní formát cdf a inverzní formát cdf (například
pnorm
aqnorm
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. -
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á funkcirtnorm
, která počítá čerpání ze zkráceného normální. Balíčektruncnorm
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:
-
using sample () with rnorm ():
sample(x=min:max, replace= TRUE, rnorm(n, mean))
-
pomocí balíčku msm a funkce rtnorm:
rtnorm(n, mean, lower=min, upper=max)
-
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]
x <- rnorm(n, mean, sd); x <- x[x > lower.limit & x < upper.limit]