【问题标题】:How to generate a random partition from an iterator in Python如何从 Python 中的迭代器生成随机分区
【发布时间】:2010-09-21 13:28:56
【问题描述】:

给定所需的分区数量,分区的大小应该几乎相等。 This question 处理列表的问题。他们没有随机属性,但那是easily added。我的问题是,我有一个迭代器作为输入,所以 shuffle 不适用。原因是我想随机划分图的节点。该图可能非常大,因此我正在寻找一种不只是创建中间列表的解决方案。

我的第一个想法是使用带有随机数函数的compress() 作为选择器。但这仅适用于两个分区。

【问题讨论】:

  • "nearly equal in size" — 所以如果有 1000 个节点,我们想把它分成 5 个部分,是 197、195、206、201、201 可以接受还是必须是 200、200、 200、200、200?
  • @KennyTM:第一个是可以接受的。这用于k-fold交叉验证,所以有些偏差是可以接受的。

标签: python random iterator partitioning


【解决方案1】:

你可以只创建 k 列表。当您收到一个值时,选择一个介于 0 和 k-1 之间的随机整数 x,并将该值放入第 x 个列表中。

平均每个列表将包含 N/k 个元素,但标准差为 √(N * 1/k * (1-1/k))。

def random_partition(k, iterable):
  results = [[] for i in range(k)]
  for value in iterable:
    x = random.randrange(k)
    results[x].append(value)
  return results

【讨论】:

  • 你能给出这个标准差的来源或解释吗?
  • @Space:这只是一个二项分布。
【解决方案2】:

你只是在处理各种分区,对吧?

def dealer( iterator, size ):
    for item in iterator
        yield random.randrange( size ), item

将每个项目分配给一个分区不是让您开始吗?

然后你可以做这样的事情来制作列表。也许不是一件好事,但它显示了如何使用该功能。

def make_lists( iterator, size ):
    the_lists = []*size
    for partition, item in dealer( iterator, size ):
        the_lists[partition].append(item)
    return the_lists

【讨论】:

  • 您可以使用来自 itertools 的 groupby 来缩短第二部分。
  • @wheaties:虽然是这样,但尚不清楚分区的用途。
【解决方案3】:

您可以通过根据每个分区中到目前为止生成的节点数调整权重来使列表的长度更加均匀。如果您选择一个函数,当(分区 n 中的节点数)>(节点数)/(分区数)时权重为 0,它们的长度将大致相等,即

权重[i] = max(numNodes/numPartitions - nodesSoFar[i],0)

(max() 是为了阻止负权重,如果你有 4 个节点和 3 个分区,可能会发生这种情况。)

然后从 1 到 sum(weights)(或 0 到 sum(weights)-1)中选择一个随机数,然后适当地选择分区。

compress() 在每个分区使用不同的选择器时有效; (x == n for x in random_partition_numbers) 之类的东西,其中 random_partition_numbers 是一个生成器。当然,您需要为每个分区复制 random_partition_numbers。这种设计本质上比较慢,因为它需要遍历每个分区的节点列表。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-10
    • 1970-01-01
    • 2012-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多