从两个列表的产品中采样的最快方法

时间:2016-04-11 16:25:36

标签: python optimization random-sample cartesian-product

我想从两个列表的产品中获取 n 样本(无需替换)。如下所示,我目前正在计算整个产品,然后从中进行采样,但这对于长列表而言在计算上是不实用的。有没有办法优化这个过程?也就是说,不必计算整个产品,而是更有效地采样?

当前天真的方法(如下所述,错误地替换替换):

from itertools import product
from random import choice

def get_sample(a,b,n):
"""return n samples from the product a and b"""
  D = list(product(a,b))
  D = [choice(D) for _ in range(n)]

  return D

3 个答案:

答案 0 :(得分:1)

如果你实际上使用list ,如果你想要 list,你应该没事。

可以找到非随机样本
from itertools import product

def get_first_n_sample(a,b,n):
"""return n samples from the product a and b"""
  D = product(a,b)
  D = [D.next() for _ in range(n)] ## if you're on Python2, use xrange!
  return D

现在,如果您只想要来自ab的某些组合的随机样本,则迭代器显然不是正确的方法,因此,itertools也不是。假设ab随机访问速度很快(例如list s,tuple s):

from random import choice

def get_random_sample(a, b):
    return (choice(a), choice(b))

获取n 唯一的样本会更复杂,但是:

from random import sample

def get_random_samples(a, b, n):
    n_prod = len(a) * len(b)
    indices = sample(range(n_prod), n)
    return [(a[idx % len(a)], b[idx // len(a)]) for idx in indices]

答案 1 :(得分:0)

如果您想要一个替换样本,代码目前的方式,您可以使用product(a, b)随机添加(choice(a), choice(b)元素:

sample = [(choice(a), choice(b)) for _ in xrange(n)]

如果您想要一个没有替换的样本,请制作一组随机索引的样本:

sample = [(a[i // len(b)], b[i % len(b)])
          for i in random.sample(xrange(len(a)*len(b)), n)]

答案 2 :(得分:-1)

不幸的是,您无法从迭代器中获取随机样本。迭代器(如product)表示您一次只知道1个值,并且您必须知道多于1个值才能提供随机性。

使用random.sample()这样的天真方法可以更有效:

from itertools import product
import random
def get_sample(a,b,n):
"""return n samples from the product a and b"""
  D = list(product(a,b))
  return random.sample(D, n)