【问题标题】:Python — Randomly fill 2D array with set number of 1'sPython — 用一组 1 随机填充二维数组
【发布时间】:2016-02-22 00:42:12
【问题描述】:

假设我有一个 0 的二维数组 (8x8)。我想用预定数量的 1 填充这个数组,但是以随机的方式。例如,假设我想在网格中随机放置 16 个 1,结果如下:

[[0, 0, 0, 1, 0, 0, 1, 0],
 [1, 0, 0, 0, 0, 0, 0, 1],
 [0, 0, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0],
 [0, 1, 0, 0, 0, 0, 0, 0],
 [0, 0, 1, 0, 1, 1, 0, 0],
 [0, 1, 0, 0, 0, 1, 0, 0],
 [0, 1, 1, 0, 0, 0, 0, 1]]

1 的最终位置无关紧要,只要它是随机的(或 Python 允许的随机)。

我的代码在技术上是有效的,但我认为它的效率非常低。我所做的只是将每个数字变为 1 的概率设置为 n/s,其中 n 是所需 1 的数量,s 是网格的大小(即元素的数量),然后我检查是否添加了正确数量的 1。这是代码(Python 2.7):

length = 8
numOnes = 16
while True:
    board = [[(random.random() < float(numOnes)/(length**2))*1 for x in xrange(length)] for x in xrange(length)]
    if sum([subarr.count(1) for subarr in board]) == 16:
        break
print board

虽然此方法有效,但它似乎是一种迂回的方法。有没有更好(即更有效)的方法来做到这一点?我预计这段代码会运行很多次(如果不是数百万,也有数十万),所以速度是一个问题。

【问题讨论】:

  • 先在一个一维数组上做,然后再改成 8X8 形状。
  • 使用随机随机播放。根据stackoverflow.com/a/976918/1653571,用 16 个向量填充长度为 8x8 的向量,并将它们打乱

标签: python arrays random


【解决方案1】:

随机播放 16 个 1 和 48 个 0 的列表:

board = [1]*16 + 48*[0]
random.shuffle(board)
board = [board[i:i+8] for i in xrange(0, 64, 8)]

或者用 0 填满棋盘,然后从 16 个位置中随机抽取一个样本放入 1:

board = [[0]*8 for i in xrange(8)]
for pos in random.sample(xrange(64), 16):
    board[pos//8][pos%8] = 1

【讨论】:

  • 我不知道shuffle的存在;感谢您指出了这一点。看看你的第二个例子,现在看起来很明显。感谢您的帮助!
  • 为了好玩,我只是尝试对这些算法进行计时,第二个比第一个快很多(31 µs vs 53 µs 在我的机器上),和我的 numpy 差不多方法(27 ​​µs)。对于大型电路板(100 万个方格),它比任何一个都快(6 毫秒,而方法 1 为 857 毫秒,我的方法为 142 毫秒)。
  • 第二种方法有个警告:如果我没记错的话,不能保证选择了 16 个 不同的 位置。也许这就是它如此之快的原因。
  • @Erwin411:绝对保证能挑到16个不同的位置。 random.sample 不会返回重复项。请参阅docs。它很可能在百万平方的棋盘上大大超过了shuffle,因为洗牌一百万个元素比挑选 16 个要多得多。
  • @user2357112:感谢您的澄清,我应该阅读文档。我假设 sample 从某些(均匀)分布中返回独立样本。
【解决方案2】:

我制作了一个,制作了零,将它们连接起来,洗牌,然后重塑。

import numpy as np
def make_board(shape, ones):
    o = np.ones(ones, dtype=np.int)
    z = np.zeros(np.product(shape) - ones, dtype=np.int)
    board = np.concatenate([o, z])
    np.random.shuffle(board)
    return board.reshape(shape)

make_board((8,8), 16)

编辑。

不管怎样,user2357112 使用 numpy 的方法很快......

def make_board(shape, ones):
    size = np.product(shape)
    board = np.zeros(size, dtype=np.int)
    i = np.random.choice(np.arange(size), ones)
    board[i] = 1
    return board.reshape(shape)

【讨论】:

  • 感谢您提供另一种选择!我总是喜欢看到人们解决这些问题的各种方式。
  • 谨防为此使用np.random.choice;使用replace=True(默认值),不能保证选择16个不同的单元格,而使用replace=False,由于实施决策不佳,它们被困在向后兼容性上,因此速度非常慢(它执行完全洗牌而不是洗牌刚好足以产生样本)。
猜你喜欢
  • 2012-07-27
  • 2017-04-17
  • 2014-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-21
  • 2017-06-22
  • 1970-01-01
相关资源
最近更新 更多