0

Given a point (x, y), how would I create n random points that their distance from (x, y) is gaussian distributed with sigma and mean as a param?

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
Ofek Ron
  • 8,354
  • 13
  • 55
  • 103

3 Answers3

9

For the 2-D distribution use numpy.random.normal. The trick is that you need to get the distribution for each dimension. So for example for a random distribution around point (4,4) with sigma 0.1

Tested in python 3.11.2, scipy 1.10.1, matplotlib 3.7.1, numpy 1.24.3

sample_x = np.random.normal(4, 0.1, 500)
sample_y = np.random.normal(4, 0.1, 500)

fig, ax = plt.subplots()
ax.plot(sample_x, sample_y, '.')
fig.show()

enter image description here

You can accomplish the same thing with numpy.random.multivariate_normal as follows:

mean = np.array([4,4])
sigma = np.array([0.1,0.1])
covariance = np.diag(sigma ** 2)
x, y = np.random.multivariate_normal(mean, covariance, 1000)

fig, ax = plt.subplots()
ax.plot(x, y, '.')

For the 3-D distribution you can use scipy.stats.multivariate_normal like so:

import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import multivariate_normal

x, y = np.mgrid[3:5:100j, 3:5:100j]
xy = np.column_stack([x.flat, y.flat])
mu = np.array([4.0, 4.0])
sigma = np.array([0.1, 0.1])
covariance = np.diag(sigma ** 2)
z = multivariate_normal.pdf(xy, mean=mu, cov=covariance)
z = z.reshape(x.shape)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(x, y, z)
fig.show()

enter image description here

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
Grr
  • 15,553
  • 7
  • 65
  • 85
2

You have to use a multi variate normal distribution. For your case, you have to use a normal distribution both on the X and Y axis. If you plot the distribution, it will be a 3 dimensional bell curve.

Use numpy's multivariate normal distribution.

numpy.random.multivariate_normal(mean, cov[, size])

mean : 1-D array_like, of length N
Mean of the N-dimensional distribution.
cov : 2-D array_like, of shape (N, N)
Covariance matrix of the distribution. It must be symmetric and positive-semidefinite for proper sampling.
size : int or tuple of ints, optional
Given a shape of, for example, (m,n,k), m*n*k samples are generated, and packed in an m-by-n-by-k arrangement. Because each sample is N-dimensional, the output shape is (m,n,k,N). If no shape is specified, a single (N-D) sample is returned.
Returns:    
out : ndarray
The drawn samples, of shape size, if that was provided. If not, the shape is (N,).
In other words, each entry out[i,j,...,:] is an N-dimensional value drawn from the distribution.
narasimman
  • 421
  • 3
  • 14
0

You can use numpy.random.normal to pull random numbers from a Gaussian distribution for the new x and y coordinates.

from numpy.random import normal

sigma = 1.0
point_0 = (0.0, 0.0)

point_1 = [i + normal(0, sigma) for i in point]

This works in this case because multiplying a Gaussian distribution in the x and y dimensions will give a Gaussian distribution in the radial dimension. I.E. exp(-r^2/a^2) = exp(-x^2/a^2) * exp(-y^2/a^2)

Chris Mueller
  • 6,490
  • 5
  • 29
  • 35