如何在2D尺寸板中随机抛出数字

时间:2018-11-13 15:56:51

标签: python numpy

我现在有一个50x50的2D尺寸的木板,上面有空的单元格。我想用0填充20%的单元格,用1填充30%的单元格,用2填充20%的单元格,用3填充20%的单元格。如何用百分比将这4个数字随机扔到板上?

  import numpy as np
  from numpy import random

  dim = 50
  map = [[" "for i in range(dim)] for j in range(dim)]
  print(map)

4 个答案:

答案 0 :(得分:2)

获得这种随机性的一种方法是从0到具有减1的单元总数的数字的随机排列开始。

perm = np.random.permutation(2500)

现在,您可以根据要获取的比例拆分排列,并将排列的条目视为数组的索引。

array = np.empty(2500)
p1 = int(0.2*2500)
p2 = int(0.3*2500)
p3 = int(0.3*2500)
array[perm[range(0, p1)]] = 0
array[perm[range(p1, p1 + p2)]] = 1
array[perm[range(p1 + p2, p3)]] = 2
array[perm[range(p1 + p2 + p3, 2500)]] = 3
array = array.reshape(50, 50)

这样,您可以确保每个数字的比例。

答案 1 :(得分:2)

由于百分比总计为1,因此可以从零开始

bsize = 50
board = np.zeros((bsize, bsize))

在这种方法中,板的位置被解释为一维位置,那么我们需要一组等于所有位置的80%的位置。

for i, pos in enumerate(np.random.choice(bsize**2, int(0.8*bsize**2), replace=False)):
    # the fisrt 30% will be set with 1
    if i < int(0.3*bsize**2):
        board[pos//bsize][pos%bsize] = 1
    # the second 30% (between 30% and 60%) will be set with 2
    elif i < int(0.6*bsize**2):
        board[pos//bsize][pos%bsize] = 2
    # the rest 20% (between 60% and 80%) will be set with 3
    else:
        board[pos//bsize][pos%bsize] = 3

最后,排名的最后20%仍为零


如@alexis在评论中所建议的那样,通过使用shuffle模块中的random方法,该方法可以变得更加简单:

随机导入随机播放

bsize = 50
board = np.zeros((bsize, bsize))

l = list(range(bsize**2))
shuffle(l)

for i, pos in enumerate(l):
        # the fisrt 30% will be set with 1
        if i < int(0.3*bsize**2):
            board[pos//bsize][pos%bsize] = 1
        # the second 30% (between 30% and 60%) will be set with 2
        elif i < int(0.6*bsize**2):
            board[pos//bsize][pos%bsize] = 2
        # the rest 20% (between 60% and 80%) will be set with 3
        elif i < int(0.8*bsize**2):
            board[pos//bsize][pos%bsize] = 3

最后20%的位置将再次保持为零。

答案 2 :(得分:0)

这是一种使用np.random.choice的方法来洗排索引,然后用插入的int的重复填充这些索引。它将按照您指定的确切比例填充数组:

import numpy as np
np.random.seed(444)

board = np.zeros(50 * 50, dtype=np.uint8).flatten()

# The "20% cells with 0" can be ignored since that is the default.
#
# This will work as long as the proportions are "clean" ints
# (I.e. mod to 0; 2500 * 0.2 is a clean 500.  Otherwise, need to do some rounding.)

rpt = (board.shape[0] * np.array([0.3, 0.3, 0.2])).astype(int)
repl = np.repeat([1, 2, 3], rpt)

idx = np.random.choice(board.shape[0], size=repl.size, replace=False)

board[idx] = repl
board = board.reshape((50, 50))

产生的频率

>>> np.unique(board, return_counts=True)
(array([0, 1, 2, 3], dtype=uint8), array([500, 750, 750, 500]))
>>> board
array([[1, 3, 2, ..., 3, 2, 2],
       [0, 0, 2, ..., 0, 2, 0],
       [1, 1, 1, ..., 2, 1, 0],
       ...,
       [1, 1, 2, ..., 2, 2, 2],
       [1, 2, 2, ..., 2, 1, 2],
       [2, 2, 2, ..., 1, 0, 1]], dtype=uint8)

方法

将板放平。当板(临时)为一维时,更容易使用索引。

rpt是每个整数重复次数的一维向量。它与[1, 2, 3]一起“压缩”以创建长度为2000的repl。(占板子尺寸的80%;在此示例中您不必担心0。)

有效地对扁平化数组的索引进行了混洗(idx),并且此混洗后的数组的长度被限制为替换候选的大小。最后,一维板中的那些索引将填充替换项,然后可以再次进行二维。

答案 3 :(得分:0)

一种不同的方法(当然,它是概率性的,因此您不会得到Brad Solomon提出的解决方案的完美比例)

import numpy as np
res = np.random.random((50, 50))

zeros = np.where(res <= 0.2, 0, 0)
ones = np.where(np.logical_and(res <= 0.5, res > 0.2), 1, 0)
twos = np.where(np.logical_and(res <= 0.8, res > 0.5), 2, 0)
threes = np.where(res > 0.8, 3, 0)

final_result = zeros + ones + twos + threes

运行

np.unique(final_result, return_counts=True)

屈服

(array([0, 1, 2, 3]), array([499, 756, 754, 491]))