2016-12-14 10 views
1

列あたりの合計が0または1に等しいmxnバイナリ配列行列を生成する最も効率的な方法は何ですか?Pythonで条件付きランダムバイナリ配列行列を生成する

この

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

mおよびnは固定されようとしているなどのsomethinを、しかしN appropied行列が見出されるまでように反復方法は長い時間がかかる可能性が500000より大きい。

+0

何 – Benjamin

答えて

1

これを行うには、標準ライブラリといくつかの賢明なリスト内包表記を使用できます。まず、それぞれが1または0の列を作成し、合計制約を満たします。次に列を列にフリップして結果を取得します。

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の単一の値、1の値なし、等であるが、この製剤の問題は、それが必須の列を有するマトリックスに拘束されることです? 1に等しい、それは列の合計が0になる可能性を避けるため、行内で 'column [random。[0、n - 1] =ランダム。ランダム(0,1) ' – jmparejaz

+0

更新されました。これで、0または1が選択されます。 – Brobin

4

あなたが列のランダムなサブセットを選択し、各列、ランダム行のためのものです。 numpyを使用してこれを行う1つの方法があります。二項分布は、あなたがで各1つの列をしたい場合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.変更にnumpy.random.binomialの第2引数を取得する列を選択するために使用されます

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)は行インデックス、各列に対して1つのランダムな選択である:ここで、かなり簡潔な方法です。 np.arange(m).reshape(-1, 1)は、配列[0, 1, ..., m-1]がshape(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]] 
関連する問題