1

I have a symmetric matrix A, with A.shape = (30, 30), and each row of A is associated with one of 3 unique labels [0, 1, 2].

I have another matrix M:

m1 = .9
m2 = .1

M = np.array([[m1, m2, m2],
              [m2, m1, m2],
              [m2, m2, m1]])

I'd like to make a new array X with shape (30, 3). Call each row of this array Xi, and its associated label k (with k being 0, 1, or 2).

I'd like the ith element of Xi to be 1 with probability m1 if i == k and m2 if i != k.

I have some working code written up to do this that uses a nested for-loop, but I'd like to do this with pure numpy. Any suggestions?

Here is the current inefficient implementation, skipping the part where I define A, labels, and M:

n_communities = 3
X = []
for i, _ in enumerate(A):  # A is a 2d array, shape (30, 30), symmetric
    Xi = []
    k = labels[i]  # labels is an array of length 30, each labels corresponds to a row of A
    for ii in range(n_communities):
        p = M[k, ii]
        Xi.append(np.random.choice([1, 0], p=[p, 1-p]))
    X.append(Xi)
X = np.array(X)
Ananda
  • 2,925
  • 5
  • 22
  • 45
Alex L
  • 367
  • 2
  • 14

1 Answers1

0

You can sample M1 and M2 independently and just insert M1 into M2 at the right positions given by the labels.

m1_arr = np.random.choice([1, 0], p=[m1, 1-m1], size=(N))
m2_arr = np.random.choice([1, 0], p=[m2, 1-m2], size=(N, 3))
m2_arr[np.arange(N), labels] = m1_arr
X = m2_arr
Ananda
  • 2,925
  • 5
  • 22
  • 45