【问题标题】:Partition array into N random chunks of different sizes with Numpy使用 Numpy 将数组划分为 N 个不同大小的随机块
【发布时间】:2020-08-24 14:22:52
【问题描述】:

使用numpy.array_splits,您可以将数组拆分为大小相等的块。有没有办法根据列表将其拆分成块?

如何将此数组拆分为 4 个块,每个块由 chunk_size 中给出的块大小决定,并由数组中的随机值组成?

import numpy as np
np.random.seed(13)
a = np.arange(20)
chunk_size = [10, 5, 3, 2]
dist = [np.random.choice(a, c) for c in chunk_size]
print(dist)

但正如预期的那样,我得到了多个重复:

[array([18, 16, 10, 16,  6,  2, 12,  3,  2, 14]),
 array([ 5, 13, 10,  9, 11]), array([ 2,  0, 19]), array([19, 11])]

例如,

  • 16 在第一个块中包含两次
  • 10 包含在第一个和第二个块中

对于np.split,这是我得到的答案:

>>> for s in np.split(a, chunk_size):
...     print(s.shape)
...
(10,)
(0,)
(0,)
(0,)
(18,)

使用np.random.choicereplace=False,仍然给出重复的元素:

import numpy as np
np.random.seed(13)
a = np.arange(20)
chunk_size = [10, 5, 3, 2]
dist = [np.random.choice(a, c, replace=False) for c in chunk_size]
print(dist)

虽然每个块现在不包含重复项,但它不会阻止,例如,7 包含在第一个和第二个块中:

[array([11, 12,  0,  1,  8,  5,  7, 15, 14, 13]),
 array([16,  7, 13,  9, 19]), array([1, 4, 2]), array([15, 12])]

【问题讨论】:

  • 你为什么使用np.random?你想从原始数组中获取连续的块还是随机元素?
  • 随机元素,甚至 np.split 给出了连续的块:-(
  • 使用replace=False
  • @Divakar:这是for循环的不同迭代,因此将被替换。
  • 会鼓励你把这些放在一起并发布你自己的答案。

标签: python numpy random


【解决方案1】:

感谢Divakar

import numpy as np
np.random.seed(13)
dist = np.arange(0, 3286, 1)
chunk_size = [975, 708, 515, 343, 269, 228, 77, 57, 42, 33, 11, 9, 7, 4, 3, 1, 1, 1, 1, 1]
dist = [np.random.choice(dist,_, replace=False) for _ in chunk_size]

【讨论】:

  • @mkrieger1:我不明白我错过了什么。你能帮帮我吗?
  • 实际上,如果我再次考虑给出的建议,我认为它不会按预期工作。
  • 您能详细说明一下吗?
  • 我认为这个想法是从数组中删除为一个块挑选的元素,以便它们不能在以下块中重复。但是为此,您必须使用 remaining 项作为下一次迭代的输入,而不是那些被挑选的。我不确定如何才能更好地解释它,因为我不知道你到底有什么不清楚的地方。
  • 也许一个例子会有所帮助:假设数组最初是 [1, 2, 3, 4, 5],并且为第一个块选择了 [2, 3]。然后对于下一次迭代,您将不得不使用剩余的项目 [1, 4, 5] 作为输入来选择。但该建议意味着使用 [2, 3] 作为再次选择的输入。
【解决方案2】:

确保a 的每个元素都包含在一个块中的一种方法是首先创建a 的随机排列,然后将其与np.split 拆分。

要从chunk_size 获取np.split 的拆分索引数组,您可以使用np.cumsum

示例

>>> import numpy as np
>>> np.random.seed(13)
>>> a = np.arange(20)
>>> b = np.random.permutation(a)
>>> b
array([11, 12,  0,  1,  8,  5,  7, 15, 14, 13,
        3, 17,  9,  4,  2,  6, 19, 10, 16, 18])

>>> chunk_size = [10, 5, 3, 2]
>>> np.cumsum(chunk_size)
array([10, 15, 18, 20])

>>> np.split(b, np.cumsum(chunk_size))
[array([11, 12,  0,  1,  8,  5,  7, 15, 14, 13]),
 array([ 3, 17,  9,  4,  2]), array([ 6, 19, 10]), array([16, 18]),
 array([], dtype=int64)]

您可以通过省略 chunk_size 中的最后一个值来避免尾随的空数组,因为 a 的大小和之前值的总和暗示了这一点:

>>> np.split(b, np.cumsum(chunk_size[:-1]))  # [10, 5, 3] -- 2 is implied
[array([11, 12,  0,  1,  8,  5,  7, 15, 14, 13]),
 array([ 3, 17,  9,  4,  2]), array([ 6, 19, 10]), array([16, 18])]

【讨论】:

    猜你喜欢
    • 2013-01-02
    • 1970-01-01
    • 2020-09-16
    • 1970-01-01
    • 2020-04-04
    • 1970-01-01
    • 2020-04-09
    • 2020-10-22
    • 2018-10-22
    相关资源
    最近更新 更多