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í, El resultado se ve así: 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
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)
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]
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)