Cómo generar una distribución normal aleatoria de enteros.

Cómo generar un entero aleatorio como con np.random.randint() , pero con una distribución normal en torno a 0.

np.random.randint(-10, 10) devuelve números enteros con una distribución uniforme discreta np.random.normal(0, 0.1, 1) devuelve flotantes con una distribución normal

Lo que quiero es una especie de combinación entre las dos funciones.

Otra forma posible de obtener una distribución discreta que se parece a la distribución normal es recurrir a una distribución multinomial donde las probabilidades se calculan a partir de una distribución normal.

 import scipy.stats as ss import numpy as np import matplotlib.pyplot as plt x = np.arange(-10, 11) xU, xL = x + 0.5, x - 0.5 prob = ss.norm.cdf(xU, scale = 3) - ss.norm.cdf(xL, scale = 3) prob = prob / prob.sum() #normalize the probabilities so their sum is 1 nums = np.random.choice(x, size = 10000, p = prob) plt.hist(nums, bins = len(x)) 

Aquí, np.random.choice elige un número entero de [-10, 10]. La probabilidad de seleccionar un elemento, digamos 0, se calcula mediante p (-0.5

El resultado se ve así:

introduzca la descripción de la imagen aquí

Puede ser posible generar una distribución similar a partir de una distribución normal truncada que se redondea a números enteros. Aquí hay un ejemplo con truncnorm de Scipy () .

 import numpy as np from scipy.stats import truncnorm import matplotlib.pyplot as plt scale = 3. range = 10 size = 100000 X = truncnorm(a=-range/scale, b=+range/scale, scale=scale).rvs(size=size) X = X.round().astype(int) 

Veamos como se ve

 bins = 2 * range + 1 plt.hist(X, bins) 

introduzca la descripción de la imagen aquí

Aquí empezamos por obtener valores de la curva de campana .

CÓDIGO:

 #--------*---------*---------*---------*---------*---------*---------*---------* # Desc: Discretize a normal distribution centered at 0 #--------*---------*---------*---------*---------*---------*---------*---------* import sys import random from math import sqrt, pi import numpy as np import matplotlib.pyplot as plt def gaussian(x, var): k1 = np.power(x, 2) k2 = -k1/(2*var) return (1./(sqrt(2. * pi * var))) * np.exp(k2) #--------*---------*---------*---------*---------*---------*---------*---------# while 1:# MAINLINE # #--------*---------*---------*---------*---------*---------*---------*---------# # # probability density function # # for discrete normal RV pdf_DGV = [] pdf_DGW = [] var = 9 tot = 0 # # create 'rough' gaussian for i in range(-var - 1, var + 2): if i == -var - 1: r_pdf = + gaussian(i, 9) + gaussian(i - 1, 9) + gaussian(i - 2, 9) elif i == var + 1: r_pdf = + gaussian(i, 9) + gaussian(i + 1, 9) + gaussian(i + 2, 9) else: r_pdf = gaussian(i, 9) tot = tot + r_pdf pdf_DGV.append(i) pdf_DGW.append(r_pdf) print(i, r_pdf) # # amusing how close tot is to 1! print('\nRough total = ', tot) # # no need to normalize with Python 3.6, # # but can't help ourselves for i in range(0,len(pdf_DGW)): pdf_DGW[i] = pdf_DGW[i]/tot # # print out pdf weights # # for out discrte gaussian print('\npdf:\n') print(pdf_DGW) # # plot random variable action rv_samples = random.choices(pdf_DGV, pdf_DGW, k=10000) plt.hist(rv_samples, bins = 100) plt.show() sys.exit() 

SALIDA:

 -10 0.0007187932912256041 -9 0.001477282803979336 -8 0.003798662007932481 -7 0.008740629697903166 -6 0.017996988837729353 -5 0.03315904626424957 -4 0.05467002489199788 -3 0.0806569081730478 -2 0.10648266850745075 -1 0.12579440923099774 0 0.1329807601338109 1 0.12579440923099774 2 0.10648266850745075 3 0.0806569081730478 4 0.05467002489199788 5 0.03315904626424957 6 0.017996988837729353 7 0.008740629697903166 8 0.003798662007932481 9 0.001477282803979336 10 0.0007187932912256041 Rough total = 0.9999715875468381 pdf: [0.000718813714486599, 0.0014773247784004072, 0.003798769940305483, 0.008740878047691289, 0.017997500190860556, 0.033159988420867426, 0.05467157824565407, 0.08065919989878699, 0.10648569402724471, 0.12579798346031068, 0.13298453855078374, 0.12579798346031068, 0.10648569402724471, 0.08065919989878699, 0.05467157824565407, 0.033159988420867426, 0.017997500190860556, 0.008740878047691289, 0.003798769940305483, 0.0014773247784004072, 0.000718813714486599] 

introduzca la descripción de la imagen aquí

La respuesta aceptada aquí funciona, pero probé la solución de Will Vousden y también funciona bien:

 import numpy as np # Generate Distribution: randomNums = np.random.normal(scale=3, size=100000) randomInts = np.round(randomNums) # Plot: axis = np.arange(start=min(randomInts), stop = max(randomInts) + 1) plt.hist(randomInts, bins = axis) 

Se ve bien no?