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.