Simuler une distribution uniforme sur un disque

24

J'essayais de simuler l'injection de points aléatoires dans un cercle, de sorte que n'importe quelle partie du cercle ait la même probabilité d'avoir un défaut. Je m'attendais à ce que le compte par zone de la distribution résultante suive une distribution de Poisson si je divise le cercle en rectangles de zone égale.

Puisqu'il ne nécessite que de placer des points dans une zone circulaire, j'ai injecté deux distributions aléatoires uniformes en coordonnées polaires: (rayon) et (angle polaire).Rθ

Mais après avoir fait cette injection, j'obtiens clairement plus de points au centre du cercle par rapport au bord.

entrez la description de l'image ici

Quelle serait la bonne façon d'effectuer cette injection à travers le cercle de telle sorte que les points soient répartis de manière aléatoire à travers le cercle?

Jonjilla
la source
Cette question a un analogue exact dans le forum Geometry: math.stackexchange.com/questions/87230/…
Aksakal

Réponses:

35

Vous souhaitez que la proportion de points soit uniformément proportionnelle à l' aire plutôt qu'à la distance à l'origine. Puisque l'aire est proportionnelle à la distance au carré, générez des rayons aléatoires uniformes et prenez leurs racines carrées. Combinez cela avec un angle polaire uniforme.

C'est rapide et simple à coder, efficace en exécution (en particulier sur une plateforme parallèle), et génère exactement le nombre de points prescrit.

Exemple

Il s'agit d'un Rcode de travail pour illustrer l'algorithme.

n <- 1e4
rho <- sqrt(runif(n))
theta <- runif(n, 0, 2*pi)
x <- rho * cos(theta)
y <- rho * sin(theta)
plot(x, y, pch=19, cex=0.6, col="#00000020")

entrez la description de l'image ici

whuber
la source
3

L'échantillonnage de rejet peut être utilisé. Cela signifie que nous pouvons échantillonner à partir d'une distribution uniforme 2D et sélectionner des échantillons qui satisfont la condition du disque.

Voici un exemple.

x=runif(1e4,-1,1)
y=runif(1e4,-1,1)

d=data.frame(x=x,y=y)
disc_sample=d[d$x^2+d$y^2<1,]
plot(disc_sample)

entrez la description de l'image ici

Haitao Du
la source
3
Il s'agit d'une bonne alternative à l'approche adoptée par le PO. Simple et efficace. Cependant, cela ne répond pas vraiment à la question de savoir comment modifier la méthode des coordonnées polaires pour produire des variations uniformément réparties. Pourquoi pourrions-nous nous en soucier? En raison des implications: une fois que vous savez comment générer des points uniformément répartis en coordonnées polaires, vous pouvez utiliser l'échantillonnage de rejet (et d'autres méthodes familières) en coordonnées polaires pour échantillonner à partir de régions qui pourraient être trop compliquées à échantillonner en coordonnées cartésiennes (pensez aux hypocycloïdes , par exemple).
whuber
1
π/4
@whuber merci de m'avoir éduqué en commentant ma réponse!
Haitao Du
3

Je vais vous donner une réponse générale à n dimensions qui fonctionne également pour les cas à deux dimensions. En trois dimensions, l'analogue d'un disque est le volume d'une boule solide (sphère).

Il y a deux approches dont je vais discuter. L'un d'eux, je l'appellerais «précis» , et vous obtiendrez une solution complète avec lui dans R. Le second que j'appelle heuristique , et ce n'est que l'idée, aucune solution complète n'est fournie.

Solution "précise"

Ma solution est basée sur les travaux de Marsaglia et Muller . Fondamentalement, cela se produit de sorte que le vecteur gaussien normalisé à sa norme vous donne les points uniformément distribués sur une hypersphère d-dimensionnelle:

entrez la description de l'image ici

1/

n <- 1e4
rho <- sqrt(runif(n))
# d - # of dimensions of hyperdisk
d = 2
r = matrix(rnorm(n*d),nrow=n,ncol=d)
x = r/rep(sqrt(rowSums(r^2))/rho,1)
plot(x[,1], x[,2], pch=19, cex=0.6, col="#00000020")

entrez la description de l'image ici

Voici un extrait de code pour le cas 3D, c'est-à-dire une boule solide:

library(scatterplot3d)
n <- 1e3
# d - # of dimensions of hyperdisk

d=3
rho <- (runif(n))^(1/d)
r = matrix(rnorm(n*d),nrow=n,ncol=d)
x = r/rep(sqrt(rowSums(r^2))/rho,1)

scatterplot3d(x[,1], x[,2], x[,3])

entrez la description de l'image ici

Approche heuristique

Vn(R)=πn2Γ(n2+1)Rn
Rn

je=1Xje2<R2

1+2

Aksakal
la source
@Silverfish, vous avez raison, j'ai corrigé la langue
Aksakal
@Silverfish, il est lent en raison de l'utilisation de variables gaussiennes, mais pourrait être plus rapide qu'un simple échantillonnage de rejet dans un cas de grande dimension, ce qui n'est pas évident pour beaucoup, bien qu'il s'agisse d'un sujet différent
Aksakal
1/,
@whuber, j'ai copié-collé, corrigé une faute de frappe sur la puissance du cube. Si nous utilisons le gaussien, l'échantillonnage de rejet n'est pas meilleur, nous devons donc utiliser quelque chose en forme de cloche plus rapide que le gaussien, vous avez raison
Aksakal
0

Voici une solution alternative en R:

n <- 1e4
## r <- seq(0, 1, by=1/1000)
r <- runif(n)
rho <- sample(r, size=n, replace=T, prob=r)
theta <- runif(n, 0, 2*pi)
x <- rho * cos(theta)
y <- rho * sin(theta)
plot(x, y, pch=19, cex=0.6, col="#00000020")

entrez la description de l'image ici

Q_Li
la source
4
Pouvez-vous expliquer cette réponse en anglais simple? Nous ne sommes pas vraiment un site d'aide sur le code, et les réponses uniquement en code devraient être découragées.
gung - Rétablir Monica
5
01r <- seq(0, 1, by=1/10)
1
@whuber Merci de l'avoir signalé. C'est en fait mon idée principale de la solution. Mon approche était de générer de nombreux cercles uniformes avec des rayons variables, et, pour chaque cercle, le nombre de points est proportionnel à la longueur de son rayon. Par conséquent, sur une longueur unitaire de cercles de rayons différents, le nombre de points est le même. Pour éviter la nature discrète, nous avons pu échantillonner à rpartir d'uniforme (0,1).
Q_Li