我正在创建一个python脚本,从这里的男性名字列表中随机选择1000个名字:http://www.census.gov/genealogy/www/data/1990surnames/names_files.html
这一切都很好,花花公子,但我希望它能根据人口普查文本文件(第二栏)提供的概率列选择名称。
在过去几个小时里,我一直试图绕过这个问题,但我还没有取得任何实际进展,甚至寻找其他答案。
有人可以帮助我或指出我正确的方向吗?在此先感谢:)
答案 0 :(得分:5)
加权选择的简单算法是:
为每个名称指定其相对概率,使得所有概率的总和为1.此相对值称为“重量”。
选择0到1之间的随机数
走完清单,在你出发时从你的号码中减去每件物品的重量
当你转到0或以下时,选择当前项目。
答案 1 :(得分:2)
数据文件的第三个列是累计概率,即第二列的运行总和。
选择与累积概率分布相关的随机名称:
import urllib2
import random
import bisect
url = 'http://www.census.gov/genealogy/www/data/1990surnames/dist.male.first'
response = urllib2.urlopen(url)
names, cumprobs = [], []
for line in response:
name, prob, cumprob, rank = line.split()
cumprob = float(cumprob)
names.append(name)
cumprobs.append(cumprob)
# normalize the cumulative probabilities to the range [0, 1]
cumprobs = [p/cumprobs[-1] for p in cumprobs]
# print(cumprobs)
# Generate 1000 names at random, using the cumulative probability distribution
N = 1000
selected = [names[bisect.bisect(cumprobs, random.random())] for i in xrange(N)]
print('\n'.join(selected))
请注意,alias method具有更好的计算复杂性,但仅选择1000个项目,这对您的用例可能不是很重要。
答案 2 :(得分:0)
适用于较小数据集的快速且非常脏黑客只是添加相关名称的次数等于加权分布。请注意,这将占用大量内存,尤其是在较大的数据集中,因此请将此视为仅适用于小加权分布的快速实现。
import random
filename = r"location/of/file"
data = list() # accumulator
with open(filename) as in_:
for line in in_:
name, prob, *_ = line.split()
for _ in range(int(float(prob)*1000)):
data.append(name)
print(random.choice(data))