2016-01-20 8 views
5

Przy założeniu pozytywnej tablicy liczb całkowitych a celem jest wygenerowanie 5 liczb losowych na podstawie ich wagi w tablicy.Generowanie liczb losowych z ważonymi prawdopodobieństwami w pythonie

Na przykład:

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

W tym przypadku numer 4 pojawił się 5 razy, w tym przypadku numer 4 powinien mieć prawdopodobieństwo 5/11 pojawiać.

Żadne numery nie powinny się powtarzać.

+0

Co masz na myśli bez powtórzeń? W tym może nie zachowuje wagi. Masz na myśli bez powtarzania indeksu? –

+0

Twoje pytanie nie jest całkiem jasne, ale jeśli masz na myśli to, co myślę, masz na myśli, oto duplikat: http://stackoverflow.com/questions/10803135/weighted-choice-short-and-simple –

+0

czy po "np .random.choice (list (set (a)), size = 5, replace = False) '? – EdChum

Odpowiedz

5

Biorąc a, tablicę liczb całkowitych dodatnich, ty” Najpierw musisz obliczyć częstotliwość każdej liczby całkowitej. Na przykład za pomocą 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 informuje częstotliwość każdej liczby całkowitej w a. Odpowiedni zestaw odważników jest zatem tablicą b/len(a). Korzystanie np.random.choice z tymi ciężarami i replace=False powinien wtedy dać ci to, czego potrzebujesz:

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

Jeśli nie pracujesz tylko z liczb całkowitych dodatnich, lub jeśli pracujesz z dużych liczb całkowitych dodatnich, @ user2357112 zwraca uwagę w komentarzach poniżej to np.unique zapewnia inne rozwiązanie. Tutaj piszesz:

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

Można również użyć ['numpy.unique'] (http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.unique.html) za pomocą opcji' return_counts', która działa znacznie lepiej, gdy twoje dane wejściowe nie są wiązką nieujemnych liczb całkowitych lub 'max (a)' jest duże. – user2357112

+0

Dzięki - zawsze wydaje mi się, że zapomniałem o parametrze 'return_counts' - byłoby to o wiele lepsze w przypadku, o którym wspomniałeś. –

+0

Czy można go zaktualizować do tego przykładu?a = [(23, 11), (10, 16), (13, 11), (12, 3), (4, 15), (10, 16), (10, 16)] b = Licznik (elem for elem in a) c = len (a) @ajcr – ccamacho

0

Prawdopodobnie szukasz numpy.random.multinomial Na przykład np.random.multinomial(1, [1/6.]*6, size=1) rzuca rzetelną kostką raz. Po uzyskaniu wyniku możesz zaktualizować wektor prawdopodobieństwa (musi sumować się do 1) według własnego uznania. Na przykład numpy.random.multinomial(1, [1/2., 1/2., 0., 0., 0., 0.], size=1).

0

Najprostszym rozwiązaniem (i być może najbardziej nieefektywne) może być następujący:

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

Wyjście może byłoby coś

[8, 2, 3, 6, 9] 
Powiązane problemy