2016-01-20 28 views
5

Dato un array intero positivo a, l'obiettivo è generare 5 numeri casuali in base al peso che hanno nell'array.Generazione di numeri casuali con probabilità ponderate in python

Ad esempio:

a = [2,3,4,4,4,4,4,6,7,8,9] 

In questo caso il numero 4 è apparso 5 volte, in questo caso il numero 4 dovrebbe avere la probabilità di 5/11 di apparire.

Nessun numero deve essere ripetuto.

+0

Cosa intendi senza ripetizione? In ciò non conserva i pesi. Intendi senza ripetizione dell'indice? –

+0

La tua domanda non è chiara, ma se intendi ciò che penso intendi, ecco un duplicato: http://stackoverflow.com/questions/10803135/weighted-choice-short-and-simple –

+0

stai cercando 'np .random.choice (list (set (a)), size = 5, replace = False) '? – EdChum

risposta

5

Dato a, un array di interi positivi, è' Prima di tutto è necessario calcolare la frequenza di ogni intero. Ad esempio, utilizzando bincount:

>>> a = [2,3,4,4,4,4,4,4,5,6,7,8,9,4,9,2,3,6,3,1] 
>>> b = np.bincount(a) 

b ti dice la frequenza di ogni intero in a. Il corrispondente set di pesi è quindi l'array b/len(a). Utilizzando np.random.choice con questi pesi e replace=False dovrebbe quindi dare quello che ti serve:

>>> np.random.choice(np.arange(len(b)), 5, p=b/len(a), replace=False) 
array([5, 9, 4, 3, 8]) 
>>> np.random.choice(np.arange(len(b)), 5, p=b/len(a), replace=False) 
array([7, 4, 6, 9, 1]) 
>>> np.random.choice(np.arange(len(b)), 5, p=b/len(a), replace=False) 
array([3, 7, 4, 9, 6]) 

Se non stai lavorando solo con numeri interi positivi, o se si lavora con grandi numeri interi positivi, @ user2357112 sottolinea nei commenti sotto che np.unique fornisce un'altra soluzione. Qui scrivi:

>>> choices, counts = np.unique(a, return_counts=True) 
>>> np.random.choice(choices, 5, p=counts/len(a), replace=False) 
array([9, 8, 2, 4, 5]) 
+1

Puoi anche usare ['numpy.unique'] (http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.unique.html) con l'opzione' return_counts', che funziona molto meglio quando il tuo input non è un insieme di numeri interi non negativi o 'max (a)' è grande. – user2357112

+0

Grazie - Mi sembra sempre di dimenticare il parametro 'return_counts' - sarebbe davvero molto meglio nei casi che hai menzionato. –

+0

È possibile aggiornarlo a questo esempio?a = [(23, 11), (10, 16), (13, 11), (12, 3), (4, 15), (10, 16), (10, 16)] b = Contatore (elem per elem in a) c = len (a) @ajcr – ccamacho

0

Probabilmente stai cercando numpy.random.multinomial Ad esempio np.random.multinomial(1, [1/6.]*6, size=1) lancia un bel dado una volta. Dopo aver ottenuto un risultato è possibile aggiornare il vettore di probabilità (deve sommarsi a 1) come desiderato. Ad esempio numpy.random.multinomial(1, [1/2., 1/2., 0., 0., 0., 0.], size=1).

0

La soluzione più semplice (e forse più inefficiente) può essere la seguente:

import random 
def get_randoms(n, a): 
    a = a[:] 
    r = [] 
    for i in range(n): 
     r.append(random.choice(a)) 
     a = [y for y in a if y != r[-1]] 
    return r 

print get_randoms(5, [2,3,4,4,4,4,4,4,5,6,7,8,9,4,9,2,3,6,3,1]) 

L'uscita può sarebbe qualcosa di simile

[8, 2, 3, 6, 9]