Create a random array of the specified shape, and then sort along the axis where you want to keep the limits, which gives us a vectorized and very efficient solution. This will be based on this smart answer on MATLAB randomly permuting columns differently . Here's the implementation -
Run Example -
In [122]: N = 10 In [123]: np.argsort(np.random.rand(8,N),axis=0)+1 Out[123]: array([[7, 3, 5, 1, 1, 5, 2, 4, 1, 4], [8, 4, 3, 2, 2, 8, 5, 5, 6, 2], [1, 2, 4, 6, 5, 4, 4, 3, 4, 7], [5, 6, 2, 5, 8, 2, 7, 8, 5, 8], [2, 8, 6, 3, 4, 7, 1, 1, 2, 6], [6, 7, 7, 8, 6, 6, 3, 2, 7, 3], [4, 1, 1, 4, 3, 3, 8, 6, 8, 1], [3, 5, 8, 7, 7, 1, 6, 7, 3, 5]], dtype=int64)
Runtime Tests -
In [124]: def sortbased_rand8(N): ...: return np.argsort(np.random.rand(8,N),axis=0)+1 ...: ...: def rand_M(N): ...: M = np.zeros(shape = (8, N)) ...: for i in range (0, N): ...: M[:, i] = np.random.choice(8, size = 8, replace = False) + 1 ...: return M ...: In [125]: N = 5000 In [126]: %timeit sortbased_rand8(N) 100 loops, best of 3: 1.95 ms per loop In [127]: %timeit rand_M(N) 1 loops, best of 3: 233 ms per loop
Thus, an acceleration of 120x is expected!