I need to generate a large number of random poker card decks. Speed is important so everything has to be in numpy matrix form.
I understand I can generate two cards
You can simulate np.random.choice(..., replace=False)'s behavior with a trick here based on argsort/argpartition. The idea is simple : We create a random array and sort it. The sorted indices thus obtained being unique would resemble np.random.choice(..., replace=False).
Since, we are looking to have a 2D array with such a feature, start with a random 2D array and for performance use np.argpartition for getting the first two sorted indices along each row to simulate 2 cards picking.
Thus, we would have a vectorized approach like so -
# N : Number of queries
# M : Number of cards to be picked
out = np.argpartition(np.random.rand(N,12*4),M,axis=1)[:,:M]
Runtime test -
In [55]: # Input params
...: N = 1000000 # Number of queries
...: M = 2 # Number of cards to be picked
...:
...: def original_app(N,M):
...: out = np.empty((N,2),dtype=int)
...: for i in range(N):
...: out[i] = np.random.choice(12*4,M, replace=False)
...: return out
...:
...: def vectorized_app(N,M):
...: return np.argpartition(np.random.rand(N,12*4),M,axis=1)[:,:M]
...:
In [56]: %timeit original_app(N,M)
1 loops, best of 3: 12.7 s per loop
In [57]: %timeit vectorized_app(N,M)
1 loops, best of 3: 678 ms per loop