在python中生成条件随机二进制数组矩阵

时间:2016-12-14 20:08:12

标签: python arrays numpy matrix random

生成与每列总和相关的mxn二进制数组矩阵的最有效方法是等于0还是1?

像这样的事情

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

m和n将被修复,但是n大于500000,因此迭代方法可能需要很长时间才能找到适当的矩阵。

4 个答案:

答案 0 :(得分:4)

您正在选择列的随机子集,然后为每列选择随机行。这是使用numpy做到这一点的一种方法。二项分布用于选择哪些列得到1.更改numpy.random.binomial的第二个参数以使用1来调整列的密度。

In [156]: m = 5

In [157]: n = 12

In [158]: a = np.zeros((m, n), dtype=int)

In [159]: cols = np.random.binomial(1, 0.7, size=n)

In [160]: a[np.random.randint(0, m, size=cols.sum()), np.nonzero(cols)[0]] = 1

In [161]: a
Out[161]: 
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0],
       [1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
       [0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0]])

如果你想在每个列中加1,这里有一个相当简洁的方法:

In [103]: m = 5

In [104]: n = 12

In [105]: a = (np.random.randint(0, m, size=n) == np.arange(m).reshape(-1, 1)).astype(int)

In [106]: a
Out[106]: 
array([[0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1],
       [0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0],
       [0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0],
       [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

np.random.randint(0, m, size=n)是行索引的随机选择,每列一个。 np.arange(m).reshape(-1, 1)是存储在具有形状(m,1)的数组中的序列[0, 1, ..., m-1]。当将其与随机值进行比较时,应用广播,因此创建具有形状(m,n)的布尔数组。只需将其转换为整数,就可以获得结果。

答案 1 :(得分:1)

您可以使用标准库和一些聪明的列表推导来执行此操作。首先,我们创建列,每个列都有10,因此我们满足求和约束。然后我们将列翻转成行以获得结果。

from random import choice, randint

def generate_matrix(m, n):
    # Generate the columns
    columns = []
    for x in range(n):
        column = [0 for y in range(m)]
        column[randint(0, m - 1)] = choice([0, 1])
        columns.append(column)
    # Rotate the columns into rows
    rows = [
        [c[x] for c in columns]
        for x in range(m)
    ]
    return rows

m, n = 5, 4
matrix = generate_matrix(m, n)

示例输出:

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

答案 2 :(得分:1)

您可以选择哪个列的值为1:

a = numpy.zeros((ysize, xsize))
a[numpy.arange(ysize), numpy.random.choice(numpy.arange(xsize), ysize, replace=False)] = 1

答案 3 :(得分:1)

  • 首先,使用列表推导和列表乘法(甚至更快)生成零填充矩阵以生成每一行。这是你必须快速的步骤。转置/复制数据会影响性能。
  • 然后循环并选择一个数字。介于0和行数* 2之间(因此有时会偏离限制,留下0填充列)。如果它在范围内,则在那里加1(你可以改变(3*nb_rows)//2来增加1的数量。这一步很快:已经分配了内存,只需标记单元格。

代码:

import random

m=7
n=5

matrix = [[0] * m for _ in range(n)]
print(matrix)
for i in range(m):
    a = random.randint(0,(3*n)//2)  # 66% chances to get a 1 somewhere
    if a < n:
        matrix[a][i] = 1

print(matrix)

结果:

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