2016-05-24 23 views
5

Come generare un numero intero casuale come con np.random.randint(), ma con una distribuzione normale circa 0.Come generare un casuale normale distribuzione di interi

np.random.randint(-10, 10) restituisce interi con un discreto uniforme distribuzione np.random.normal(0, 0.1, 1) rendimenti galleggia con una distribuzione normale

Quello che voglio è un tipo di combinazione tra le due funzioni.

+10

La distribuzione normale è continua per definizione, quindi la risposta a questa domanda dipende da come lo vuoi discretizzare. Una possibile soluzione è campionare da 'np.random.normal' e arrotondare il risultato a un numero intero. –

risposta

14

Un altro modo possibile per ottenere una distribuzione discreta che assomiglia la distribuzione normale è quello di trarre da una distribuzione multinomiale dove le probabilità sono calcolate da una distribuzione normale.

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)) 

Qui, np.random.choice raccoglie un intero da [-10, 10]. La probabilità di selezionare un elemento, ad esempio 0, è calcolata da p (-0.5 < x < 0.5) dove x è una variabile casuale normale con media zero e deviazione standard 3. Scelto std. dev. come 3 perché in questo modo p (-10 < x < 10) è quasi 1.

Il risultato assomiglia a questo:

enter image description here

+0

Perché hai aggiunto e sottratto 0.5 in 'xL' e' xU'? –

+2

Per una distribuzione continua, P (x = 0) = 0 (questo è vero per qualsiasi altro numero). La probabilità è definita per intervalli. Qui, per associare una probabilità a 0 (e ad altri interi) ho usato l'intervallo (-0,5, 0,5). Fondamentalmente perché la domanda chiedeva numeri interi. Per 1, è (0.5, 1.5). – ayhan

+0

Perché non hai preso 'ss.norm.pdf (x, scale = 3)'? –

4

Potrebbe essere possibile generare una distribuzione simile da Truncated Normal Distribution arrotondata agli interi. Ecco un esempio di Scipy truncnorm().

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) 

Vediamo come si presenta

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

enter image description here

+0

Apprezzo le risposte sia da @ayhan che da bakkal. Per favore, lo chiedo solo per conoscenza; Non desidero insultare nessuna delle due risposte. Solo guardando la trama, Bakkal's è più simmetrico. Sembrano entrambi sufficienti e dal codice sembrano ugualmente validi. Ma la mia comprensione è debole. Esiste un metodo oggettivamente migliore? –

+1

@RobertLugg la simmetria relativamente più elevata potrebbe essere dovuta al fatto che la dimensione del campione è maggiore. Detto questo, penso che il codice in questa risposta sia più semplice. – bakkal