Generating permutation array without replacement

Viewed 124

I am trying to get a matrix of size (1000, 7) in which each row is a random permutation of the numbers 0 to 6. I am using the following code to implement the requirement.

import numpy as np

permute_array = []
for i in range(1000):
    permute_array.append(np.random.permutation(7))
permute_array = np.array(permute_array)

This is slow as the for loop takes quite some time to run. Is there a one shot way of generating this array? Thanks.

4 Answers
import numpy as np
permute_array = np.argsort(np.random.rand(1000, 7), axis=1)

There are several ways to do so, if you just need a solution for this case (this function) you can just create array (1000,7) fill it with range(7) and then shuffle each row using np.apply_along_axis:

(Not recommended for an abstract solution but it's really fast)

import numpy as np
a = np.full((1000, 7),fill_value=np.arange(7))
np.apply_along_axis(func1d=np.random.shuffle, axis=1, arr=a)
print(a[:5])

performance: 2.96 ms ± 21.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Another elegant and also fast and more abstract solution is to use your permutation function:

import numpy as np
a = np.array([np.random.permutation(7) for i in range(1000)])
print(a[:5])

performance: 2.13 ms ± 30.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

The second solution looks a bit faster.

Maybe you could use itertools.permutations to generate all the permutations (5040 in your case) and then use something like random.choices to select 1000 permutations at random. It would avoid to have two identical rows, which your code can't. Don't know if it's faster.

You can create an array from zeros and then replace it with permutation, with apply_along_axis from np which is very fast.

import itertools

np.apply_along_axis(lambda _: list(itertools.permutations(range(7))), 0, np.zeros(1000))
Related