filling numpy array with random element from another array

I’m not sure if this is possible but here goes. Suppose I have an array:

array1 = [0,.1,.2,.3,.4,.5,.6,.7,.8,.9,1]

and now I would like to create a numpy 1D array consisting of 5 elements that are randomly drawn from array1 AND with the condition that the sum is equal to 1. Example is something like, a numpy array that looks like [.2,.2,.2,.1,.1].

  • currently I use the random module, and choice function that looks like this:
    range1= np.array([choice(array1),choice(array1),choice(array1),choice(array1),choice(array1)])
    then checking range1 to see if it meets the criteria; I’m wondering if there is faster way , something similar to
    randomArray = np.random.random() instead.
  • Would be even better if I can store this array in some library so that if I try to generate 100 of such array, that there is no repeat but this is not necessary.

Best answer

You can use numpy.random.choice if you use numpy 1.7.0+:

>>> import numpy as np
>>> array1 = np.array([0,.1,.2,.3,.4,.5,.6,.7,.8,.9,1])
>>> np.random.choice(array1, 5)
array([ 0. ,  0. ,  0.3,  1. ,  0.3])
>>> np.random.choice(array1, 5, replace=False)
array([ 0.6,  0.8,  0.1,  0. ,  0.4])

To get 5 elements that the sum is equal to 1,

  • generate 4 random numbers.
  • substract the sum of 4 numbers from 1 -> x
  • if x included in array1, use that as final number; or repeat

>>> import numpy as np
>>> 
>>> def solve(arr, total, n):
...     while True:
...         xs = np.random.choice(arr, n-1)
...         remain = total - xs.sum()
...         if remain in arr:
...             return np.append(xs, remain)
... 
>>> array1 = np.array([0,.1,.2,.3,.4,.5,.6,.7,.8,.9,1])
>>> print solve(array1, 1, 5)
[ 0.1  0.3  0.4  0.2  0. ]

Another version (assume given array is sorted):

EPS = 0.0000001
def solve(arr, total, n):
    while True:
        xs = np.random.choice(arr, n-1)
        t = xs.sum()
        i = arr.searchsorted(total - t)
        if abs(t + arr[i] - total) < EPS:
            return np.append(xs, arr[i])