Pythonic way to sparsely randomly populate array?
Question: Problem: Populate a 10 x 10 array of zeros randomly with 10 1's, 20 2's, 30
3's.

**I don't actually have to use an array, rather I just need coordinates for
the positions where the values would be. It's just easier to think of in terms
of an array.**

I have written several solutions for this, but they all seem to be non-
straight forward and non-pythonic. I am hoping someone can give me some
insight. My method has been using a linear array of 0--99, choosing randomly
(np.random.choice) 10 values, removing them from the array, then choosing 20
random values. After that, I convert the linear positions into (y,x)
coordinates.

    
    
    import numpy as np
    
    dim = 10
    grid = np.arange(dim**2)
    
    n1 = 10
    n2 = 20
    n3 = 30
    
    def populate(grid, n, dim):
        pos = np.random.choice(grid, size=n, replace=False)
        yx = np.zeros((n,2))
        for i in xrange(n):
            delPos = np.where(grid==pos[i])
            grid = np.delete(grid, delPos)
            yx[i,:] = [np.floor(pos[i]/dim), pos[i]%dim]
        return(yx, grid)
    
    pos1, grid = populate(grid, n1, dim)
    pos2, grid = populate(grid, n2, dim)
    pos3, grid = populate(grid, n3, dim)
    

**Extra** Suppose when I populate the 1's, I want them all on one half of the
"array." I can do it using my method (sampling from grid[dim**2/2:]), but I
haven't figured out how to do the same with the other suggestions.


Answer: To generate the array, you can use
[`numpy.random.choice`](http://docs.scipy.org/doc/numpy/reference/generated/numpy.random.choice.html).

    
    
    np.random.choice([0, 1, 2, 3], size=(10,10), p=[.4, .1, .2, .3])
    

Then you can convert to coordinates. Note that `numpy.random.choice` generates
a random sample using probabilities `p`, and thus you are not guaranteed to
get the _exact_ proportions in `p`.

**Extra**

If you want to have all the `1`s on a particular side of the array, you can
generate two random arrays and then
[`hstack`](http://docs.scipy.org/doc/numpy/reference/generated/numpy.hstack.html#numpy.hstack)
them. The trick is to slightly modify the probabilities of each number on each
side.

    
    
    In [1]: import numpy as np
    In [2]: rem = .1/3 # amount to de- / increase the probability for non-1s
    In [3]: A = np.random.choice([0, 1, 2, 3], size=(5, 10),
                                  p=[.4-rem, .2, .2-rem, .3-rem])
    In [4]: B = np.random.choice([0, 2, 3], size=(5, 10), p=[.4+rem, .2+rem, .3+rem])
    In [5]: M = np.hstack( (A, B) )
    In [6]: M
    Out[1]: 
    array([[1, 1, 3, 0, 3, 0, 0, 1, 1, 0, 2, 2, 0, 2, 0, 2, 3, 3, 2, 0],
           [0, 3, 3, 3, 3, 0, 1, 3, 1, 3, 0, 2, 3, 0, 0, 0, 3, 3, 2, 3],
           [1, 0, 0, 0, 1, 0, 3, 1, 2, 2, 0, 3, 0, 3, 3, 0, 0, 3, 0, 0],
           [3, 2, 3, 0, 3, 0, 1, 2, 3, 2, 0, 0, 0, 0, 3, 2, 0, 0, 0, 3],
           [3, 3, 0, 3, 3, 3, 1, 3, 0, 3, 0, 2, 0, 2, 0, 0, 0, 3, 3, 3]])
    

Here, because I'm putting _all_ the `1`s on the left, I double the probability
of `1` and decrease the probability of each number equally. The same logic
applies when creating the other side.

