繁体   English   中英

如何在Python中进行组合和随机采样

[英]How to make combinations and random sample in Python

我想对所有组合进行组合和随机选择。 输出是元组,但我不知道如何随机选择一定数量的元组。

代码

import itertools
from itertools import combinations, permutations
from random import choice, sample

list1 = ("Mon", "Tue","Wed","Tru","Fri","Sat","Sun")
for i in combinations(list1, 3):
    print(i,end=' ')

产量

('Mon', 'Tue', 'Wed') ('Mon', 'Tue', 'Tru') ('Mon', 'Tue', 'Fri') ('Mon', 'Tue', 'Sat') ('Mon', 'Tue', 'Sun') ('Mon', 'Wed', 'Tru') ('Mon', 'Wed', 'Fri') ('Mon', 'Wed', 'Sat') ('Mon', 'Wed', 'Sun') ('Mon', 'Tru', 'Fri') ('Mon', 'Tru', 'Sat') ('Mon', 'Tru', 'Sun') ('Mon', 'Fri', 'Sat') ('Mon', 'Fri', 'Sun') ('Mon', 'Sat', 'Sun') ('Tue', 'Wed', 'Tru') ('Tue', 'Wed', 'Fri') ('Tue', 'Wed', 'Sat') ('Tue', 'Wed', 'Sun') ('Tue', 'Tru', 'Fri') ('Tue', 'Tru', 'Sat') ('Tue', 'Tru', 'Sun') ('Tue', 'Fri', 'Sat') ('Tue', 'Fri', 'Sun') ('Tue', 'Sat', 'Sun') ('Wed', 'Tru', 'Fri') ('Wed', 'Tru', 'Sat') ('Wed', 'Tru', 'Sun') ('Wed', 'Fri', 'Sat') ('Wed', 'Fri', 'Sun') ('Wed', 'Sat', 'Sun') ('Tru', 'Fri', 'Sat') ('Tru', 'Fri', 'Sun') ('Tru', 'Sat', 'Sun') ('Fri', 'Sat', 'Sun') 

我尝试如下

S =sample(i,4)
print(S)

产量

ValueError: Sample larger than population or is negative

预期输出如下

('Wed', 'Sat', 'Sun') ('Tru', 'Fri', 'Sat') ('Tru', 'Fri', 'Sun') ('Tru', 'Sat', 'Sun') 

而不是打印将其附加到其他列表

import itertools
from itertools import combinations, permutations
from random import choice, sample

list1 = ("Mon", "Tue","Wed","Tru","Fri","Sat","Sun")
list2 = []
for i in combinations(list1, 3):
    list2.append(i)

S =sample(list2,4)
print(S)

import random
list1 = ["Mon", "Tue","Wed","Tru","Fri","Sat","Sun"]
def make_combo(len1,len2):
    return [tuple([random.choice(list1) for i in range(len2)]) for i in range(len1)]

这使得len2长度的len1元组列表

i是一个元组,而不是整个生成的序列。 您必须首先从combinations()输出创建一个列表,然后从该列表中采样:

weekdays = ("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun")
S = sample(list(combinations(weekdays, 3)), 4)

注意:我更正了该列表中Thu的拼写,并选择了一个更友好的变量名。

演示:

>>> from itertools import combinations
>>> from random import sample
>>> weekdays = ("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun")
>>> sample(list(combinations(weekdays, 3)), 4)
[('Mon', 'Tue', 'Sun'), ('Wed', 'Thu', 'Sun'), ('Mon', 'Wed', 'Fri'), ('Mon', 'Thu', 'Sun')]

但是,我会根据星期的名称创建随机样本,并将它们添加到集合中,以确保您拥有唯一的元组,直到拥有所需的大小为止:

def sample_combinations(choices, size, count):
    collected = {tuple(sample(weekdays, size)) for _ in range(count)}
    while len(collected) < count:
        collected.add(tuple(sample(weekdays, size)))
    return list(collected)

S = sample_combinations(weekdays, 3, 4)

产生相同的输出,没有重复的元组:

>>> sample_combinations(weekdays, 3, 4)
[('Tue', 'Fri', 'Wed'), ('Sun', 'Sat', 'Fri'), ('Mon', 'Fri', 'Thu'), ('Tue', 'Mon', 'Sat')]

这可能会更有效率,因为它避免了必须预先生成所有可能的排列。 可能的组合越多,这一点就越重要。 对于您的工作日示例,只有35种可能的组合,但是其他输入参数(要选择的名称,组合元组的大小)可能产生数百万种可能的组合。

例如,如果要选择3 个小写ASCII字母 ,则需要生成2600个元组的列表,然后才能从中提取4个元组。 添加大写ASCII字母后,计数增加到22100。使用10位数字,您需要处理39711个元组等。但是上面的函数仅需要生成4个唯一的组合,仅此而已。 如果有重复的话,它不必进一步迭代。

对于大量的组合这将大大加快速度

>>> import timeit
>>> timeit.timeit(
...     "sample(list(combinations(ascii_letters, 3)), 4)",
...     "from itertools import combinations; from random import sample; from string import ascii_letters",
...     number=10**3
... )   # 1000 repeats, so result is in milliseconds / execution
1.1539382990158629
>>> timeit.timeit(
    "sample_combinations(ascii_letters, 3, 4)",
    "from __main__ import sample_combinations; from string import ascii_letters",
    number=10**6
)  # 100.000 repeats, so 1000 times more, microseconds / execution
14.198360272974242

使用ASCII字母(22100种可能的组合),然后使用random.sample()加载所有这些组合需要1.539毫秒,但是使用上述函数需要14.2 微秒 快约80倍。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM