2016-12-14 91 views
1

什么可能是生成mxn二进制数组矩阵的最有效方法?这种矩阵与每列的总和约束等于0或1?在python中生成条件随机二进制数组矩阵

事端这样

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

m和n要被固定的,但n为大于50万,直到一个appropied矩阵被发现迭代方法可能需要很长的时间。

+0

什么是行轴的期望的1单值,没有的1值等 – Benjamin

回答

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] 
+0

但与此制剂中的问题是,它是制约了强制列中的矩阵等于1,这是避免列和可能等于0的可能性,所以在行 '列[随机。randint(0,n - 1)] = 1 #可编写为: 列[random.randint(0,n - 1)] = random.randint(0,1)' – jmparejaz

+0

已更新。它现在选择0或1。 – Brobin

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:

a = numpy.zeros((ysize, xsize)) 
a[numpy.arange(ysize), numpy.random.choice(numpy.arange(xsize), ysize, replace=False)] = 1 
1
  • 首先,使用列表理解和列表乘(甚至更快),生成各行产生零填充的矩阵。这是你必须快速的步骤。转置/复制数据会妨碍性能。
  • 然后循环并选择一个数字。在0和行数* 2之间(所以它有时会超出限制,留下0填充的列)。如果它在范围内,放1有(你可以通过(3*nb_rows)//2改变,增加的人的数量这一步是快:内存已分配,只是标记细胞

代码:

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]]