Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Numpy random array from 0 to 99, including both

I'm trying to create a np array with size (80,10) so each row has random values with range 0 to 99.

I've done that by

np.random.randint(99, size=(80, 10))

But I would like to always include both 0 and 99 as values in each row.

So two values in each row are already defined and the other 8 will be random.

How would I accomplish this? Is there a way to generate an array size (80,8) and just concatenate [0,99] to every row to make it (80,10) at the end?

like image 640
lalakersfan29 Avatar asked Sep 06 '25 03:09

lalakersfan29


2 Answers

As suggested in the comments by Tim, you can generate a matrix with random values not including 0 and 99. Then replace two random indices along the second axis with the values 0 and 99.

rand_arr = np.random.randint(low=1, high=98, size=(80, 10))
rand_indices = np.random.rand(80,10).argsort(axis=1)[:,:2]
np.put_along_axis(rand_arr, rand_indices, [0,99], axis=1)

The motivation for using argsort is that we want random indices along the second axis without replacement. Just generating a random integer matrix for values 0-10 with size=(80,2) will not guarantee this.

In your scenario, you could do np.argpartion with kth=2 instead of np.argsort. This should be more efficient.

like image 139
Kevin Avatar answered Sep 07 '25 19:09

Kevin


I've tried a few things and this is what I came up with

def generate_matrix(low, high, shape):
    x, y = shape
    values = np.random.randint(low+1, high-1, size=(x, y-2))
    predefined = np.tile([low, high], (x, 1))
    values = np.hstack([values, predefined])
    for row in values:
        np.random.shuffle(row)
    return values

Example usage

>>> generate_matrix(0, 99, (5, 10))
array([[94,  0, 45, 99, 18, 31, 78, 80, 32, 17],
       [28, 99, 72,  3,  0, 14, 26, 37, 41, 80],
       [18, 78, 71, 40, 99,  0, 85, 91,  8, 59],
       [65, 99,  0, 45, 93, 94, 16, 33, 52, 53],
       [22, 76, 99, 15, 27, 64, 91, 32,  0, 82]])

The way I approached it:

Generate an array of size (80, 8) in the range [1, 98] and then concatenate 0 and 99 for each row. But you probably need the 0/99 to occur at different indices for each row, so you have to shuffle them. Unfortunately, np.random.shuffle() only shuffles the rows among themselves. And if you use np.random.shuffle(arr.T).T, or random.Generator.permutation, you don't shuffle the columns independently. I haven't found a vectorised way to shuffle the rows independently other than using a Python loop.

Another way:

You can generate an array of size (80, 10) in the range [1, 98] and then substitute in random indices the values 0 and 99 for each row. Again, I couldn't find a way to generate unique indices per row (so that 0 doesn't overwrite 99 for example) without a Python loop. Since I couldn't find a way to avoid Python loops, I opted for the first way, which seemed more straightforward.

like image 22
Reti43 Avatar answered Sep 07 '25 20:09

Reti43