Jeg har brug for at generere tilfældige tal efter Normalfordeling inden for intervallet $ (a, b) $. (Jeg arbejder i R.)

Jeg kender funktionen rnorm(n,mean,sd) vil generere tilfældige tal efter normalfordeling, men hvordan indstilles intervalgrænserne inden for det? Er der nogen specielle R-funktioner til rådighed til det?

Kommentarer

  • Hvorfor vil du gøre dette? Hvis det ‘ er afgrænset, kan det ‘ ikke virkelig være normalt. Hvad prøver du at opnå?
  • x <- rnorm(n, mean, sd); x <- x[x > lower.limit & x < upper.limit]
  • @Hugh that ‘ er fantastisk … så længe du ikke ‘ er ligeglad med, hvor mange tilfældige værdier du får.

Svar

Det lyder som om du vil simulere fra en trunkeret distribution og i dit specifikke eksempel , en trunkeret normal .

Der findes en række forskellige metoder til at gøre det, nogle enkle, andre relativt effektiv.

Jeg illustrerer nogle tilgange på dit normale eksempel.

  1. Her er en meget enkel metode til at generere en ad gangen (i en slags pseudokode ):

    $ \ tt {repeat} $ generer $ x_i $ fra N (middel, sd) $ \ tt {indtil} $ lavere $ \ leq x_i \ leq $ øvre

    indtast billedebeskrivelse her

    Hvis det meste af fordelingen er inden for rammerne, er dette ret rimeligt, men det kan blive ret langsomt, hvis genererer du næsten altid uden for grænserne.

    I R kan du undgå en ad gangen løkke ved at beregne området inden for rammerne og generere nok værdier til at du næsten kan være sikker på at efter at have kastet ud værdierne uden for grænserne havde du stadig så mange værdier, som det var nødvendigt.

  2. Du kan bruge accept-afvis med en passende majoriseringsfunktion over intervallet (i nogle tilfælde ensartet vil være god nok). Hvis grænserne var rimeligt smalle i forhold til s.d. men du var ikke langt ind i halen, en ensartet majorering ville f.eks. fungere okay med det normale.

    indtast billedebeskrivelse her

  3. Hvis du har en rimelig effektiv cdf og invers cdf (såsom pnorm og qnorm til normalfordeling i R) kan du bruge den inverse-cdf-metode, der er beskrevet i første afsnit i det simulerende afsnit af Wikipedia-siden på den afkortede normal . [I virkeligheden dette er det samme som at tage en trunkeret uniform (trunkeret ved de krævede kvantiler, hvilket faktisk ikke kræver nogen afvisning overhovedet, da det bare er en anden uniform) og anvende den omvendte normale cdf til det. Bemærk, at dette kan mislykkes, hvis du “er langt ind i halen]

    indtast billedbeskrivelse her

  4. Der er andre tilgange; den samme Wikipedia-side nævner tilpasning af ziggurat -metoden, der skal fungere for en række distributioner.

samme Wikipedia-link nævner to specifikke pakker (begge på CRAN) med funktioner til generering af afkortede normaler:

MSM -pakken i R har en funktion, rtnorm, der beregner tegninger fra en trunkeret normal. truncnorm -pakken i R har også funktioner til at trække fra en afkortet normal.


Når man ser sig rundt, er meget af dette dækket af svar på andre spørgsmål (men ikke ligefrem duplikater, da dette spørgsmål er mere generelt end bare den afkortede normale) … se yderligere diskussion i

a. Dette svar

b. Xi “et” svar her , som har et link til hans arXiv-papir (sammen med nogle andre værdifulde svar).

Svar

Den hurtige og beskidte tilgang er at bruge 68-95-99.7 reglen .

I en normalfordeling falder 99,7% af værdierne inden for 3 standardafvigelser fra gennemsnittet. Så hvis du indstiller dit gennemsnit til midten af din ønskede minimumsværdi og maksimale værdi og indstiller din standardafvigelse til 1/3 af dit gennemsnit, får du (for det meste) værdier, der falder inden for det ønskede interval. Så kan du bare rydde op i resten.

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) 

Jeg stod for nylig over for det samme problem og forsøgte at generere tilfældige studiekarakterer til testdata. I koden ovenfor har jeg brugt pmax og pmin til at erstatte værdier uden for grænserne med min eller maks. værdi.Dette fungerer til mit formål, fordi jeg genererer temmelig små mængder data, men for større mængder vil det give dig mærkbare ujævnheder ved min- og maksimumværdierne. Så afhængigt af dine formål kan det være bedre at kassere disse værdier, udskift dem med NA s, eller “genrul” dem, indtil de “er inden for grænserne.

Kommentarer

  • Hvorfor gider du gøre dette? Det er så simpelt at generere normale tilfældige tal og slippe dem, der har brug for trunkering, at det ikke er ‘ t nødvendigt at være kompliceret, medmindre den ønskede trunkering er tæt på 100% af området af densiteten.
  • Måske fortolker jeg ‘ det originale spørgsmål forkert. Jeg stødte på dette spørgsmål, mens jeg prøvede at finde ud af, hvordan man opnå en ikke-direkte-statsrelateret programmeringsopgave i R, og jeg ‘ har først nu bemærket, at denne side er en statistik stackexchange , ikke en programmering stackexchange. 🙂 I mit tilfælde ville jeg generere en bestemt mængde tilfældige heltal med værdier fra 0 til 100, og jeg ville have, at de genererede værdier skulle falde på en flot klokkekurve over det område. Siden jeg skrev dette, har jeg ‘ indset, at sample(x=min:max, prob=dnorm(...)) måske er en lettere måde at gøre det på.
  • @Glen_b Aaron Wells nævner sample(x=min:max, prob=dnorm(...)) som synes lidt kortere end dit svar.
  • Men bemærk, at sample() trick kun er nyttigt hvis du ‘ forsøger at vælge tilfældige heltal eller et andet sæt diskrete, foruddefinerede værdier.

Svar

Ingen af svarene her giver en effektiv metode til at generere trunkerede normale variabler, der ikke involverer afvisning af vilkårligt store antal genererede værdier. Hvis du vil generere værdier ud fra en afkortet normalfordeling med specificerede nedre og øvre grænser $ a < b $ , dette kan gøres — uden afvisning — ved at generere ensartede kvantiler over det kvantile område, der er tilladt af trunkeringen, og bruge omvendt transformation sampling for at få tilsvarende normale værdier .

Lad $ \ Phi $ betegne CDF for standardnormalfordelingen. Vi vil generere $ X_1, …, X_N $ fra en afkortet normalfordeling (med gennemsnitlig parameter $ \ mu $ og variansparameter $ \ sigma ^ 2 $ ) $ ^ \ dolk $ med lavere og øvre trunkeringsgrænser $ a < b $ . Dette kan gøres som følger:

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

Der er ingen indbygget funktion til genererede værdier fra den afkortede distribution, men det er trivielt at programmere denne metode ved hjælp af almindelige funktioner til generering af tilfældige variabler. Her er en simpel R -funktion rtruncnorm, der implementerer denne metode i et par kodelinjer.

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

Dette er en vektoriseret funktion, der genererer N IID tilfældige variabler fra den trunkerede normalfordeling. Det ville være let at programmere funktioner til andre afkortede distributioner via den samme metode. Det ville heller ikke være for svært at programmere tilknyttede tætheds- og kvantile-funktioner til den afkortede distribution.


$ ^ \ dolk $ Bemærk, at trunkeringen ændrer middelværdien og variansen af fordelingen, så $ \ mu $ og $ \ sigma ^ 2 $ er ikke middelværdien og variansen for den trunkerede fordeling.

Svar

Tre måder har fungeret for mig:

  1. ved hjælp af sample () med rnorm ():

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

  2. ved hjælp af msm-pakken og rtnorm-funktionen:

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

  3. ved hjælp af rnorm () og specificering af de nedre og øvre grænser, som Hugh har skrevet ovenfor:

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

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *