【问题标题】:Created a Sample from Weighted Random Choice从加权随机选择创建样本
【发布时间】:2013-11-09 22:27:09
【问题描述】:

我想从给定的字典中创建一个包含 3 个选项的样本。字典长度可以是可变的。

我在之前的代码中所做的是创建一个加权值字典,在本例中是 12 个值和键。

但无法从我的 random.choice 中检索样本。

使用 python 3

我的字典是

dictionary = {'Three': 14.4, 'Five': 11.2, 'Two': 14.4, 'Thirteen': 3.3, 'One': 17.6, 'Seven': 3.3, 'Nine': 3.3, 'Ten': 3.3, 'Twelve': 3.3, 'Eight': 3.3, 'Four': 12.0, 'Six': 10.4}

我尝试从字典的随机选择中检索 3 个样本。

my_sample = random.sample(random.choice(dictionary), 3)
print(my_sample)

但是得到这个错误

Traceback (most recent call last):
  File "c_weights.py", line 38, in <module>
    my_sample = random.sample(random.choice(dictionary), 3)
  File "/usr/lib64/python3.3/random.py", line 252, in choice
    return seq[i]
KeyError: 11

试图得到

My_sample = ('One', 'Four','Twelve') 例如。

编辑: 只是要清楚我的工作目标是什么。

('One', 'Four','Twelve')
('Two', 'One','Six')
('Four', 'Two','Five')
('One', 'Eight','Two')
('Thirteen', 'Three','Six')

如此独特的集合基于字典中的加权概率(或元组,如果更好的话)

【问题讨论】:

  • 我没有得到这个加权部分。您希望"Three""Thirteen" 更频繁地成为样本成员吗? random.samplerandom.choice 都不会这样做,但这就是人们说“加权随机选择”时通常所追求的。
  • 我看不出你的加权随机性的逻辑。还有其他方法可以做到这一点。 Here 是 numpy 的一种方式。我个人使用this way
  • @DSM 是的,我希望从样本中抽取的“一”按我提供的权重按比例超过“十三”。
  • @kobejohn 所以我应该创建一个元组而不是创建字典?我认为字典更好,因为键是我希望检索集合的重要部分。

标签: python random python-3.x dictionary


【解决方案1】:

您无法成功地将random.choice() 应用于字典 - 它是序列的函数,而不是映射。

试试:

random.sample(dictionary, 3)

返回一个包含 3 个随机键的列表。

【讨论】:

  • 但它会使用我在提取样本时包含的权重吗?
  • @sayth,当然不是。有关解决此问题的方法,请参阅有关您问题的其他 cmets。但目前还不清楚你想做什么。来自加权总体的大小为 one 的样本很有意义。但是您正在尝试random.sample() 完全意味着您不希望重复,然后很清楚您想要从加权总体中获得大小为 3 的样本。
  • 假设(为了使数字更简单)您的 dict 是 {'One': 1, 'Two': 10, 'Three': 100} 并且您正在采集大小为 2 的样本。究竟是什么抽样的概率应该是('One', 'Two')吗? ('One', 'Three')的? ('Two', 'Three')?
  • @sayth,你想要的是不可能的。假设您有 3 个项目,A 的权重为 1,B 的权重为 2,C 的权重为 7(所以加到 10)。假设您想要大小为 2 的样本。对于选择 (A, B)(A, C)(B, C) 的概率,您想要究竟是多少?不管你回答什么,样本中ABC的相对频率都不会在1::2::7的比例上。想想看。逻辑上的不一致不会仅仅因为您正在查看更大的人群和更大的样本量而消失 - 它们只是变得更难看到
  • 所以在我给你的具体小例子中,你希望C 在 70% 的时间里首先被选中。给定C,你想要A 1/3 的时间和B 其余的时间......等等。把这些加起来,AB 的概率是 17/360(以任意顺序),14 AC 为 /45,BC 为 77/120。所以我们会在样本中看到A 17/360 + 14/45 = 43/120 ~= 35.8% 的时间,与 10% 相差甚远。只是让你知道这就是你会得到的;-)
【解决方案2】:

好吧,这可能充满了错误/统计错误,但这对你来说是一个起点,我现在没有更多时间。这也是非常低效的!话虽如此,我希望它有所帮助:

import random

d= {'Three': 14.4, 'Five': 11.2, 'Two': 14.4, 'Thirteen': 3.3, 'One': 17.6, 'Seven': 3.3, 'Nine': 3.3, 'Ten': 3.3, 'Twelve': 3.3, 'Eight': 3.3, 'Four': 12.0, 'Six': 10.4}
total_weight = sum(d.values())
n_items = 3
random_sample = list()
d_mod = dict(d)

for i in range(n_items):
    random_cumulative_weight = random.uniform(0, total_weight)
    this_sum = 0.0
    for item, weight in d_mod.items():
        this_sum += weight
        if this_sum >= random_cumulative_weight:
            random_sample.append(item)
            break
    del(d_mod[item])
    total_weight -= this_sum

random_sample

产生 ['七'、'九'、'二'] 等。

【讨论】:

    猜你喜欢
    • 2015-07-05
    • 2010-09-08
    • 2017-12-26
    • 2011-05-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多