2014-01-15 16 views
3

我已經實現了以下類,根​​據輸入頻率'p'生成'p'或'q'。但是,如果頻率小於用於存儲選項的列表大小,則此實現會中斷。有沒有一種方法可以實現這一點,以便爲p的任何值工作?魯棒加權隨機字符串生成器

from random import random 

class AlleleGenerator(object): 
    """ 
    allele generator - will break if p < 0.001 
    """ 
    def __init__(self, p): 
     """construct class and creates list to select from""" 
     self.values = list() 
     for i in xrange(int(1000*p)): 
      self.values.append('p') 
     while len(self.values) <= 1000: 
      self.values.append('q') 
    def next(self): 
     """Returns p or q based on allele frequency""" 
     rnd = int(random() * 1000) 
     return self.values[rnd] 
    def __call__(self): 
     return self.next() 
+2

必讀,如果你需要適應兩個以上的可能值://eli.thegreenplace:Bendersky對[加權隨機生成(HTTP的文章。 net/2010/01/22/weighted-random-generation-in-python /)。 – DSM

回答

6

請勿使用self.values。在next,只是生成0和1之間的隨機數,並返回'p'如果隨機數小於p

from random import random 

class AlleleGenerator(object): 
    def __init__(self, p): 
     """construct class and creates list to select from""" 
     self.p = p 
    def next(self): 
     """Returns p or q based on allele frequency"""    
     return 'p' if random() < self.p else 'q' 
    def __call__(self): 
     return self.next() 

此外,小心not to use classes當一個功能就足夠了。 例如,你可以考慮使用一個generator function

from random import random 

def allele_generator(p): 
    while True: 
     yield 'p' if random() < p else 'q' 

agen = allele_generator(0.001) 
for i in range(3): 
    print(next(agen)) 
+0

您可能會想使用'random.uniform()'來確保均勻分佈。我不認爲'random.random()'產生一個足夠均勻分佈的值序列,使得這個算法在統計上是準確的。 –

+2

@SilasRay:[random.uniform](http://hg.python.org/cpython/file/0056aaf42bf7/Lib/random.py#l340)調用'random.random'。 'random.uniform'對於在任意範圍'[a,b]'中產生隨機數很有用。對於範圍'[0,1]',使用'random.random'。 – unutbu

+0

嗯,真的......看看代碼,我看到他們使用了來自谷歌的Wichman-Hill,看起來可靠地產生了一個很好的均勻分佈。我立場糾正。 :) –