randomly controlling the percentage of non zero values in a matrix using python
<p>I am looking to create matrices with different levels of sparsity. I intend to do that by converting all the values that are nonzero in the data matrix to 1's and the remaining entries would be 0.</p>

<p>I was able to achieve that using the following code. But I am not sure how would I be able to randomly make the 1's to 0's in the final matrix with control on the percentage of 1's.</p>

<p>For eg:</p>

<p>the numpy.random.choice </p>

<blockquote>
  <p>numpy.random.randint(2, size = data_shape, p=[0.75,0.25])</p>
</blockquote>

<p>enables us to create matrices with control over the percentage of 1's. How do I control the percentage of 1's in a similar way in the final matrix?</p>

<pre><code>import numpy as np
import scipy.sparse as sp
import numpy.ma as ma

indptr = np.array([0, 2, 3, 6])
indices = np.array([0, 2, 2, 0, 1, 2])
data = np.array([1, 2, 3, 4, 5, 6])
matrix = sp.csr_matrix((data, indices, indptr), shape=(3, 3)).toarray()
print(matrix)

mask = ma.masked_greater(matrix, 0)
print(mask)
print(mask.mask)

matrix2 = mask.mask
int_matrix = matrix2.astype(int)
print(int_matrix)
</code></pre>

<p>Output:</p>

<pre><code>Data matrix:
[[1 0 2]
 [0 0 3]
 [4 5 6]]
Masked matrix:
[[-- 0 --]
 [0 0 --]
 [-- -- --]]
Masked values:
[[ True False  True]
 [False False  True]
 [ True  True  True]]
Final matrix
[[1 0 1]
 [0 0 1]
 [1 1 1]]
</code></pre>

<p>Thanks for the help!!!</p>

<p>You could do something like this -</p>

<pre><code>idx = np.flatnonzero(a)
N = np.count_nonzero(a!=0) - int(round(0.25*a.size))
np.put(a,np.random.choice(idx,size=N,replace=False),0)
</code></pre>

<p><strong>Sample run</strong></p>

<p>1) Input array :</p>

<pre><code>In [259]: a
Out[259]: 
array([[0, 1, 0, 1, 1],
       [0, 1, 1, 0, 1],
       [1, 1, 0, 0, 0],
       [1, 0, 1, 1, 0]])
</code></pre>

<p>2) Get the non-zero indices :</p>

<pre><code>In [260]: idx = np.flatnonzero(a)
</code></pre>

<p>3) Get the number of non-zeros to be set as zeros :</p>

<pre><code>In [261]: N = np.count_nonzero(a!=0) - int(round(0.25*a.size))
</code></pre>

<p>4) Finally we select N randomly chosen indices from idx and set those in <code>a</code> as zeros :</p>

<pre><code>In [262]: np.put(a,np.random.choice(idx,size=N,replace=False),0)
</code></pre>

<p>5) Verify array -</p>

<pre><code>In [263]: a
Out[263]: 
array([[0, 0, 0, 1, 0],
       [0, 1, 0, 0, 0],
       [1, 0, 0, 0, 0],
       [1, 0, 0, 1, 0]])
</code></pre>

<p>6) Finally, we see the percentage of non-zeros and verify it to be <code>25%</code> :</p>

<pre><code>In [264]: np.count_nonzero(a!=0)/float(a.size)
Out[264]: 0.25
</code></pre>

python python-3.x numpy matrix scipy