【问题标题】:python: sampling without replacement from a 2D gridpython:从二维网格无替换采样
【发布时间】:2011-06-18 09:46:57
【问题描述】:

我需要来自range(n) 的所有可能的数字元组中的一个样本,无需替换。也就是说,我有一个集合 (0,0), (0,1), ..., (0,n), (1,0), (1,1), ..., (1,n ), ..., (n,0), (n,1), (n,n),我正在尝试获取这些元素中的 k 个样本。我希望避免明确构建此集合。

如果我需要来自数字序列而不是数字元组的样本,我知道random.sample(range(n), k) 既简单又高效。

当然,我可以显式构建包含所有可能的 (n * n = n^2) 元组的列表,然后调用 random.sample。但如果kn^2 小得多,那可能效率不高。

我不确定 Python 2 和 3 的效率是否相同;我使用 Python 3。

【问题讨论】:

  • 元组是序列,因此您的句子“需要来自数字序列而不是数字元组的样本”。没有意义。你的意思是你需要一个来自元组序列的样本?在这种情况下还不清楚这些元组的外观。
  • 您的代码(random.sample(range(n), k) 适用于所有序列、元组、列表、字符串和collections.Sequence 的任何子类。您尝试过您的代码了吗?问题是什么?
  • @Regebro: '来自元组的样本' = '从 n 个元组序列中的 k 个元组的样本'。 '来自序列的样本' = '来自 n 个元素的序列中的 k 个元素的样本'。我将编辑问题以澄清。 @S.Lott:我的意思是我不能引用序列 ((0,0), (0,1), (0,2), (1,0), (1,1), ( 1,2), (2,0), (2,1), (2,2)) 作为一个简单的range 我可以简单地应用sample

标签: python algorithm random python-3.x


【解决方案1】:

根据您选择的数量,最简单的方法可能是跟踪您已经选择的东西(通过set),然后重新选择,直到你得到你没有的东西'已经选好了。

另一种选择是只使用一些简单的数学:

numbers_in_nxn = random.sample(range(n*n), k) # Use xrange in Python 2.x
tuples_in_nxn = [divmod(x,n) for x in numbers_in_nxn]

【讨论】:

  • 我认为您的意思是random.sample(range(n*n),k),因为当我意识到您已将这部分放入其中时,我就是这么写的。
  • +1 第二个选项对我来说似乎很完美(在将 n * n 替换为 range(n*n) 并将 100 替换为 n 之后)。考虑到sample 据称效率很高,我想不出什么时候从集合中抽取会更好。
  • 您可以将(x % n, x // n) 替换为divmod(x,n)
  • +1 以获得聪明的答案(显然,理解 OP 想要什么)。如果将 range 更改为 xrange,在 Python 2.x 中也会很好。
  • @Kabie, divmod(x,n) 会返回 (x // n, x % n) 而不是 (x % n, x // n),所以它并不完全相同,尽管我认为这并不重要(因此也认为 @JF Sebastian 的评论是无关)。
【解决方案2】:

没有尝试(手头没有python):

random.shuffle(range(n))[:k]

参见 cmets。没睡够……

【讨论】:

  • 这不会给出n x n 中的元组,因为它永远不会给出,比如(1,1)
  • 但是“没有替换”是什么意思呢?啊,现在我明白了。 k 个长度为 n 的不同元组。
【解决方案3】:

你说:

当然,我可以显式构建 包含所有可能的列表 (n * n = n^2) 元组,然后调用 随机抽样。但这可能是 如果 k 小得多,则效率不高 大于 n^2。

那么,在你随机选择一个元组之后构建元组怎么样?即,如果您可以在随机选择要选择的元组之前构建元组,则可以先进行选择,然后再构建。

我不明白你的元组应该是什么样子,但这里有一个例子,虽然我知道你的元组都是相同的长度,这说明了原理:

不要这样做:

>>> import random
>>> all_sequences = [range(x) for x in range(10)]
>>> all_sequences
[[], [0], [0, 1], [0, 1, 2], [0, 1, 2, 3], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5, 6], [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7, 8]]
>>> random.sample(all_sequences, 3)
[[0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5, 6, 7, 8]]

你会这样做:

>>> import random
>>> selection = random.sample(range(10), 3)
>>> [range(x) for a in selection]
[[0, 1, 2, 3, 4, 5, 6, 7, 8], [0, 1, 2, 3, 4, 5, 6, 7, 8], [0, 1, 2, 3, 4, 5, 6, 7, 8]]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-23
    • 2023-02-05
    • 2023-03-28
    相关资源
    最近更新 更多