我现在有一个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)
答案 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]))