Come simulare i dati che soddisfano vincoli specifici come avere una media e una deviazione standard specifiche?


56

Questa domanda è motivata dalla mia domanda sulla meta-analisi . Ma immagino che sarebbe utile anche per insegnare contesti in cui si desidera creare un set di dati che rispecchi esattamente un set di dati pubblicato esistente.

So come generare dati casuali da una determinata distribuzione. Quindi, ad esempio, se leggessi dei risultati di uno studio che aveva:

  • una media di 102,
  • una deviazione standard di 5,2 e
  • una dimensione del campione di 72.

Potrei generare dati simili usando rnormin R. Ad esempio,

set.seed(1234)
x <- rnorm(n=72, mean=102, sd=5.2)

Naturalmente la media e la SD non sarebbero esattamente uguali rispettivamente a 102 e 5.2:

round(c(n=length(x), mean=mean(x), sd=sd(x)), 2)
##     n   mean     sd 
## 72.00 100.58   5.25 

In generale, sono interessato a come simulare i dati che soddisfano una serie di vincoli. Nel caso precedente, i constaints sono la dimensione del campione, la media e la deviazione standard. In altri casi, potrebbero esserci ulteriori vincoli. Per esempio,

  • un minimo e un massimo nei dati o nella variabile sottostante potrebbero essere noti.
  • è possibile che la variabile assuma solo valori interi o solo valori non negativi.
  • i dati potrebbero includere più variabili con correlazioni note.

Domande

  • In generale, come posso simulare dati che soddisfano esattamente una serie di vincoli?
  • Ci sono articoli scritti su questo? Ci sono programmi in R che lo fanno?
  • Per esempio, come potrei e dovrei simulare una variabile in modo che abbia una media e una sd specifiche?

1
Perché vuoi che siano esattamente come i risultati pubblicati? Non sono queste stime della media della popolazione e della deviazione standard dato il loro campione di dati. Data l'incertezza in quelle stime, chi può dire che il campione che mostri sopra non è coerente con le loro osservazioni?
Ripristina Monica - G. Simpson,

4
Poiché questa domanda sembra raccogliere risposte che mancano il segno (IMHO), vorrei sottolineare che concettualmente la risposta è semplice: i vincoli di uguaglianza sono trattati come distribuzioni marginali e i vincoli di disuguaglianza sono analoghi multivariati di troncamento. Il troncamento è relativamente facile da gestire (spesso con campionamento del rifiuto); il problema più difficile equivale a trovare un modo per campionare queste distribuzioni marginali. Ciò significa che i margini di campionamento sono dati in base alla distribuzione e al vincolo o che si integrano per trovare la distribuzione marginale e il campionamento da esso.
whuber

4
A proposito, l'ultima domanda è banale per le famiglie di distribuzione su scala locale. Ad esempio, x<-rnorm(72);x<-5.2*(x-mean(x))/sd(x)+102fa il trucco.
whuber

1
@whuber, come allude il cardinale in un commento alla mia risposta (che menziona questo "trucco") e un commento ad un'altra risposta - questo metodo, in generale, non manterrà le variabili all'interno della stessa famiglia distributiva, poiché stai dividendo dalla deviazione standard del campione.
Macro

5
@Macro Questo è un buon punto, ma forse la risposta migliore è "ovviamente non avranno la stessa distribuzione"! La distribuzione desiderata è la distribuzione subordinata ai vincoli. In generale, ciò non proviene dalla stessa famiglia della distribuzione principale. Ad esempio, ogni elemento di un campione di dimensione 4 con media 0 e SD 1 ricavato da una distribuzione normale avrà una probabilità quasi uniforme su [-1,5, 1,5], poiché le condizioni pongono limiti superiori e inferiori sui possibili valori.
whuber

Risposte:


26

In generale, per rendere la media e la varianza del campione esattamente uguali a un valore predefinito, è possibile spostare e ridimensionare in modo appropriato la variabile. In particolare, se è un esempio, quindi le nuove variabiliX1,X2,...,Xn

Zi=c1(XiX¯sX)+c2

dove è la media del campione e è che la varianza del campione è tale che la media del campione di è esattamente e la loro varianza del campione è esattamente . Un esempio costruito in modo simile può limitare l'intervallo:s 2 X =1X¯=1ni=1nXiZic2sX2=1n1i=1n(XiX¯)2Zic2c1

Bi=a+(ba)(Ximin({X1,...,Xn})max({X1,...,Xn})min({X1,...,Xn}))

produrrà un set di dati che è limitato all'intervallo . ( a , b )B1,...,Bn(a,b)

Nota: questi tipi di spostamento / ridimensionamento cambieranno, in generale, la famiglia distributiva dei dati, anche se i dati originali provengono da una famiglia di scale di posizione.

Nel contesto della distribuzione normale, la mvrnormfunzione in R consente di simulare i dati normali (o multivariati normali) con una media / covarianza campione specificata impostando empirical=TRUE. Nello specifico, questa funzione simula i dati della distribuzione condizionale di una variabile normalmente distribuita, dato che la media del campione e la (co) varianza sono uguali a un valore predefinito . Si noti che le distribuzioni marginali risultanti non sono normali, come sottolineato da @whuber in un commento alla domanda principale.

Ecco un semplice esempio univariato in cui la media del campione (da un campione di ) è vincolata a 0 e la deviazione standard del campione è 1. Possiamo vedere che il primo elemento è molto più simile a una distribuzione uniforme di una normale distribuzione:n=4

library(MASS)
 z = rep(0,10000)
for(i in 1:10000)
{
    x = mvrnorm(n = 4, rep(0,1), 1, tol = 1e-6, empirical = TRUE)
    z[i] = x[1]
}
hist(z, col="blue")

                  inserisci qui la descrizione dell'immagine


1
Lo non sarà distribuito normalmente, sebbene possano essere approssimativamente così se la dimensione del campione è grande. Il primo commento alla risposta di @ Sean allude a questo. Zi
cardinale il

1
Bene, questa è una cosa abbastanza naturale da voler fare ... e spesso non causa troppi problemi.
cardinale il

1
+1. Nell'esempio, l'uniforme è la risposta esatta , tra l'altro. (L'apparente dropoff alle estremità della trama è un artefatto di come R disegna gli istogrammi.)
whuber

1
@whuber, grazie per aver motivato questo esempio. Dato che le distribuzioni marginali cambiano una volta che si condiziona la media / varianza del campione, sembra che la migliore "risposta" nello spirito della domanda del PO sia solo quella di simulare dati con media / varianza della popolazione pari a quella riportata come campione quantità (come suggerito dal PO stesso), non è vero? In questo modo, si ottengono quantità di campione "simili" a quelle desiderate e le distribuzioni marginali sono ciò che si voleva che fossero.
Macro

1
@whuber, Se il tuo campione è normale, allora ha una distribuzione , sì? La "nuova" variabile in questione sarà solo una combinazione lineare di . t T iTi=(XiX¯)/stTi
Macro

22

Per quanto riguarda la tua richiesta di documenti, c'è:

Questo non è proprio quello che stai cercando, ma potrebbe servire da grinta per il mulino.


C'è un'altra strategia che nessuno sembra aver menzionato. È possibile generare (pseudo) dati casuali da un set di dimensioni tale che l'intero set soddisfi i vincoli purché i restanti dati siano fissati su valori appropriati. I valori richiesti dovrebbero essere risolvibili con un sistema di equazioni, algebra e grasso al gomito. N k k kNkNkkk

Ad esempio, per generare un insieme di dati da una distribuzione normale che avrà una determinata media del campione, , e varianza, , sarà necessario fissare i valori di due punti: e . Poiché la media di esempio è: deve essere: La varianza del campione è: quindi (dopo aver sostituito sopra , sventando / distribuendo e riorganizzando ... ) noi abbiamo: ˉ x s 2 y z ˉ x = N - 2 i = 1 x iNx¯s2yz
yy=N ˉ x

x¯=i=1N2xi+y+zN
y
y=Nx¯(i=1N2xi+z)
s2=i=1N2(xix¯)2+(yx¯)2+(zx¯)2N1
y a = - 2 b = 2 ( N ˉ x - N - 2 i = 1 x i ) c z
2(Nx¯i=1N2xi)z2z2=Nx¯2(N1)+i=1N2xi2+[i=1N2xi]22Nx¯i=1N2xi(N1)s2
Se prendiamo , e come negazione dell'RHS, possiamo risolvere per usando la formula quadratica . Ad esempio, in , è possibile utilizzare il seguente codice: a=2b=2(Nx¯i=1N2xi)czR
find.yz = function(x, xbar, s2){
  N    = length(x) + 2
  sumx = sum(x)
  sx2  = as.numeric(x%*%x)          # this is the sum of x^2
  a    = -2
  b    = 2*(N*xbar - sumx)
  c    = -N*xbar^2*(N-1) - sx2 - sumx^2 + 2*N*xbar*sumx + (N-1)*s2
  rt   = sqrt(b^2 - 4*a*c)

  z    = (-b + rt)/(2*a)
  y    = N*xbar - (sumx + z)
  newx = c(x, y, z)
  return(newx)
}

set.seed(62)
x    = rnorm(2)
newx = find.yz(x, xbar=0, s2=1)
newx                                # [1] 0.8012701  0.2844567  0.3757358 -1.4614627
mean(newx)                          # [1] 0
var(newx)                           # [1] 1

Ci sono alcune cose da capire su questo approccio. Innanzitutto, non è garantito il funzionamento. Ad esempio, è possibile che le prime dati sono tali da non valori e esistono che faranno la varianza dei risultanti impostato uguale . Tener conto di: y z s 2N2yzs2

set.seed(22)    
x    = rnorm(2)
newx = find.yz(x, xbar=0, s2=1)
Warning message:
In sqrt(b^2 - 4 * a * c) : NaNs produced
newx                                # [1] -0.5121391  2.4851837        NaN        NaN
var(c(x, mean(x), mean(x)))         # [1] 1.497324

In secondo luogo, mentre la standardizzazione rende le distribuzioni marginali di tutte le vostre variate più uniformi, questo approccio influenza solo gli ultimi due valori, ma rende le loro distribuzioni marginali distorte:

set.seed(82)
xScaled = matrix(NA, ncol=4, nrow=10000)
for(i in 1:10000){
  x           = rnorm(4)
  xScaled[i,] = scale(x)
}

(inserisci trama)

set.seed(82)
xDf = matrix(NA, ncol=4, nrow=10000)
i   = 1
while(i<10001){
  x       = rnorm(2)
  xDf[i,] = try(find.yz(x, xbar=0, s2=2), silent=TRUE)  # keeps the code from crashing
  if(!is.nan(xDf[i,4])){ i = i+1 }                      # increments if worked
}

(inserisci trama)

In terzo luogo, il campione risultante potrebbe non sembrare molto normale; potrebbe sembrare che abbia "valori anomali" (ovvero punti che provengono da un processo di generazione di dati diverso rispetto al resto), dal momento che essenzialmente è così. È meno probabile che ciò costituisca un problema con dimensioni del campione più grandi, poiché le statistiche del campione dai dati generati dovrebbero convergere ai valori richiesti e quindi necessitano di meno aggiustamenti. Con campioni più piccoli, è sempre possibile combinare questo approccio con un algoritmo di accettazione / rifiuto che riprova se il campione generato ha statistiche di forma (ad esempio, asimmetria e curtosi) che sono al di fuori dei limiti accettabili (cfr. Commento di @ cardinale ) o estendere questo approccio per generare un campione con una media fissa, varianza, asimmetria ekurtosi (lascerò l'algebra a te, però). In alternativa, è possibile generare un piccolo numero di campioni e utilizzare quello con la statistica Kolmogorov-Smirnov più piccola (diciamo).

library(moments)
set.seed(7900)  
x = rnorm(18)
newx.ss7900 = find.yz(x, xbar=0, s2=1)
skewness(newx.ss7900)                       # [1] 1.832733
kurtosis(newx.ss7900) - 3                   # [1] 4.334414
ks.test(newx.ss7900, "pnorm")$statistic     # 0.1934226

set.seed(200)  
x = rnorm(18)
newx.ss200 = find.yz(x, xbar=0, s2=1)
skewness(newx.ss200)                        # [1] 0.137446
kurtosis(newx.ss200) - 3                    # [1] 0.1148834
ks.test(newx.ss200, "pnorm")$statistic      # 0.1326304 

set.seed(4700)  
x = rnorm(18)
newx.ss4700 = find.yz(x, xbar=0, s2=1)
skewness(newx.ss4700)                       # [1]  0.3258491
kurtosis(newx.ss4700) - 3                   # [1] -0.02997377
ks.test(newx.ss4700, "pnorm")$statistic     # 0.07707929S

(aggiungi trama)


10

La tecnica generale è il "Metodo di rifiuto", in cui rifiuti solo i risultati che non soddisfano i tuoi vincoli. A meno che tu non abbia una sorta di guida (come MCMC), potresti generare molti casi (a seconda del tuo scenario) che vengono respinti!

Dove stai cercando qualcosa come una deviazione media e standard e puoi creare una metrica di distanza di qualche tipo per dire quanto sei lontano dal tuo obiettivo, puoi usare l'ottimizzazione per cercare le variabili di input che ti danno l'output desiderato valori.

Come un brutto esempio in cui cercheremo un vettore uniforme casuale con lunghezza 100 che abbia media = 0 e deviazione standard = 1.

# simplistic optimisation example
# I am looking for a mean of zero and a standard deviation of one
# but starting from a plain uniform(0,1) distribution :-)
# create a function to optimise
fun <- function(xvec, N=100) {
  xmin <- xvec[1]
  xmax <- xvec[2]
  x <- runif(N, xmin, xmax)
  xdist <- (mean(x) - 0)^2 + (sd(x) - 1)^2
  xdist
}
xr <- optim(c(0,1), fun)

# now lets test those results
X <- runif(100, xr$par[1], xr$par[2])
mean(X) # approx 0
sd(X)   # approx 1

7
I vincoli che si verificano con probabilità zero sono difficili da soddisfare. ;-) Per l'esempio specifico a portata di mano, uno spostamento e una dilatazione appropriati raggiungono facilmente gli obiettivi dichiarati , anche se si potrebbe voler analizzare un po 'più a fondo per vedere come la distribuzione dei dati è perturbata da tale operazione.
cardinale il

Grazie. Certamente sarebbe facile rifiutare osservazioni inferiori al minimo e maggiori del massimo. E vedo come potresti definirlo un problema di ottimizzazione. Sarebbe bello vedere alcuni esempi o magari avere dei suggerimenti su cosa leggere dopo.
Jeromy Anglim,

1
@cardinal - concordato. Si dovrebbe guardare alle distribuzioni (cioè un istogramma) di entrambi i numeri simulati di input e output poiché a volte questi possono sembrare davvero molto strani!
Sean,

9

Ci sono programmi in R che lo fanno?

Il pacchetto Runuran R contiene molti metodi per generare variate casuali. Utilizza le librerie C del progetto UNU.RAN (generatore di numeri universali non uniformi RAndom). La mia conoscenza del campo della generazione casuale di variabili è limitata, ma la vignetta Runuran offre una buona panoramica. Di seguito sono riportati i metodi disponibili nel pacchetto Runuran, tratti dalla vignetta:

Distribuzioni continue:

  • Campionamento di rifiuto adattivo
  • Rifiuto della densità trasformata inversa
  • Interpolazione polinomiale di CDF inversa
  • Metodo semplice rapporto di uniformi
  • Rifiuto della densità trasformata

Distribuzioni discrete:

  • Discreta inversione automatica dell'inversione
  • Metodo Alias-Urn
  • Metodo tabella guida per inversione discreta

Distribuzioni multivariate:

  • Algoritmo Hit-and-Run con metodo Ratio-of-Uniforms
  • Metodo del rapporto delle uniformi ingenuo multivariato

Esempio:

Per un rapido esempio, supponiamo di voler generare una distribuzione normale limitata tra 0 e 100:

require("Runuran")

## Normal distribution bounded between 0 and 100
d1 <- urnorm(n = 1000, mean = 50, sd = 25, lb = 0, ub = 100)

summary(d1)
sd(d1)
hist(d1)

La urnorm()funzione è una comoda funzione wrapper. Credo che dietro le quinte utilizzi il metodo Polinomial Interpolation of Inverse CDF ma non ne sono sicuro. Per qualcosa di più complesso, diciamo, una distribuzione normale discreta limitata tra 0 e 100:

require("Runuran")

## Discrete normal distribution bounded between 0 and 100
# Create UNU.RAN discrete distribution object
discrete <- unuran.discr.new(pv = dnorm(0:100, mean = 50, sd = 25), lb = 0, ub = 100)

# Create UNU.RAN object using the Guide-Table Method for Discrete Inversion
unr <- unuran.new(distr = discrete, method = "dgt")

# Generate random variates from the UNU.RAN object
d2 <- ur(unr = unr, n = 1000)

summary(d2)
sd(d2)
head(d2)
hist(d2)

3

Sembra che ci sia un pacchetto R che soddisfi le tue esigenze pubblicato proprio ieri! simstudy Di Keith Goldfeld

Simula set di dati per esplorare tecniche di modellazione o comprendere meglio i processi di generazione dei dati. L'utente specifica una serie di relazioni tra covariate e genera dati basati su queste specifiche. Gli insiemi di dati finali possono rappresentare dati provenienti da studi di controllo randomizzati, progetti di misure ripetute (longitudinali) e studi randomizzati a grappolo. La mancanza può essere generata usando vari meccanismi (MCAR, MAR, NMAR).


1
Né nella vignetta né nella home page del programma viene menzionato l'esatto incontro dei vincoli. Perché pensi che questo pacchetto soddisfi i requisiti per attingere a distribuzioni condizionate?
gg

2

Questa è una risposta che arriva così tardi che è presumibilmente insignificante, ma c'è sempre una soluzione MCMC alla domanda. Vale a dire, per proiettare la densità congiunta del campione sul collettore definito dai vincoli, ad esempio L'unico problema è quindi la simulazione di valori su quella varietà, ovvero la ricerca di una parametrizzazione della dimensione corretta. Un articolo del 2015 di Bornn, Shephard e Solgi studia proprio questo problema (con una risposta interessante se non ultima ). n i = 1 xi=μ0

i=1nf(xi)
i=1nxi=μ0i=1nxi2=σ02

2

Questa risposta considera un altro approccio al caso in cui si desidera forzare i variati a trovarsi in un intervallo specificato e dettare ulteriormente la media e / o la varianza.

Limitare la nostra attenzione all'intervallo unitario . Usiamo una media ponderata per la generalità, quindi correggiamo alcuni pesi con o impostiamo se si desidera una ponderazione standard. Supponiamo che le quantità e rappresentino la media (ponderata) desiderata e la varianza (ponderata), rispettivamente. Il limite superiore su è necessario perché questa è la varianza massima possibile su un intervallo di unità. Siamo interessati a disegnare alcune variate da con queste restrizioni del momento.[0,1]wk[0,1]k=1Nwk=1wk=1/Nμ(0,1)0<σ2<μ(1μ)σ2x1,...,xN[0,1]

Innanzitutto disegniamo alcune variate da qualsiasi distribuzione, come . Questa distribuzione influenzerà la forma della distribuzione finale. Quindi li vincoliamo all'intervallo unitario usando una funzione logistica:y1,...,yNN(0,1)[0,1]

xk=11+e(ykvh)

Prima di farlo, tuttavia, come visto nell'equazione sopra, trasformiamo gli con la traduzione e la scala . Questo è analogo alla prima equazione nella risposta di @ Macro. Il trucco ora è scegliere e modo che le variabili trasformate abbiano i momenti desiderati. Cioè, abbiamo bisogno di una o entrambe le seguenti cose: ykhvhvx1,...,xN

μ=k=1Nwk1+e(ykvh)σ2=k=1Nwk(1+e(ykvh))2(k=1Nwk1+e(ykvh))2

L'inversione di queste equazioni per e analiticamente non è fattibile, ma farlo numericamente è semplice, soprattutto perché i derivati ​​rispetto a e sono facili da calcolare; ci vogliono solo alcune iterazioni del metodo di Newton.vhvh

Come primo esempio, supponiamo che ci preoccupiamo solo di limitare la media ponderata e non la varianza. Fix , , , . Quindi per le distribuzioni sottostanti , e finiamo con i seguenti istogrammi, rispettivamente, e tale che la media delle variate sia esattamente (anche per la piccola ):v = 1 w k = 1 / N N = 200000 N ( 0 , 1 ) N ( 0 , 0,1 ) Unif ( 0 , 1 ) 0,8 Nμ=0.8v=1wk=1/NN=200000N(0,1)N(0,0.1)Unif(0,1) 0.8N

Esempio 1

Quindi, limitiamo sia la media che la varianza. Prendi , , e considera le tre deviazioni standard desiderate . Utilizzando la stessa distribuzione sottostante , ecco gli istogrammi per ciascuno:w k = 1 / N N = 2000 σ = 0,1 , 0,05 , 0,01 N ( 0 , 1 )μ=0.2wk=1/NN=2000σ=0.1,0.05,0.01N(0,1)

Esempio 2

Si noti che questi possono sembrare un po 'distribuiti in beta, ma non lo sono.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.