Home > Net >  how to use fastrand in a numpy array
how to use fastrand in a numpy array

Time:09-25

I'd like to use fastrand library provided on this GitHub page, which works fine when used to generate random numbers one at a time. For instance,

#pip install fastrand==1.2.4
import fastrand

print(fastrand.pcg32bounded(1001))
975

However, I would like to use this method in a numpy array to generate multiple numbers for certain indices where the upper bound is the number existing in the corresponding index. Suppose I have a 2 by 5 numpy array.

import fastrand
arr = np.array([[8, 7, 4, 9, 9], [9, 9, 9, 7, 9]])
print(arr,"\n")

[[8 7 4 9 9]
 [9 9 9 7 7]] 

Now, I substract random numbers for the first two numbers in the second row. I can easily do this by using np.random.randint as shown below.

arr[1,:2]-=  np.random.randint(arr[1,:2]) 
print(arr)
[[8 7 4 9 9]
 [4 1 9 7 7]]

My goal is to use fastrand instead of np.random.randint to increase the performance. Is this possible by any chance?

Edit: On a second note, another issue is how to place a lower bound on the generated random number. However, I can ask this question as a new post if needed.

CodePudding user response:

I'm not going to import fastrand, but I think this function simulates its action. I'm not sure about the end point adjustment. Here I assume the desired range is [0,n), not including the end point as numpy does. Tweak as necessary.

In [52]: def fastrand(n):
    ...:     return random.randint(0,n-1)
    ...:

That can be substituted into your initial list comprehension as:

In [53]: arr = np.array([[fastrand(8) 2 for i in range(5)]for j in range(2)])
In [54]: arr
Out[54]: 
array([[6, 7, 2, 6, 2],
       [5, 3, 9, 4, 7]])

As I claimed in the comments, you can just as well generate all random numbers with one call. For small arrays it may be slower, but it should scale better. But you'll have to do your own time tests.

In [55]: np.random.randint(2,10,(2,5))
Out[55]: 
array([[9, 5, 8, 6, 7],
       [8, 7, 7, 9, 8]])

The randint with array upper bound is:

In [56]: np.random.randint(arr[0,:2])
Out[56]: array([2, 4])
In [57]: np.random.randint(arr[0,:2])
Out[57]: array([5, 0])

with a scalar random int generator you'd have to use a list comprehension as before. Here it's just 1d:

In [58]: [fastrand(i) for i in arr[0,:2]]
Out[58]: [4, 6]
In [59]: [fastrand(i) for i in arr[0,:2]]
Out[59]: [5, 4]

Again, there's a trade off between the code of iteration, and the slower numpy setup.

  • Related