Home > Net >  Are there ways to change a numpy value by chance?
Are there ways to change a numpy value by chance?

Time:08-09

I am trying to change an element in a numpy array by chances so it looks like this :

arr = np.random.randint(1,9, data_length).astype(str)
arr[arr == "1"] = "1" if random.randint(1,2) == 1 else "A"

# result should be 1 would have a 50% chance of becoming an "A"

For some reason, this does not work, the actual result is :

>>> arr
array(['1', '3', '5', '7', '3', '7', '3', '4', '2', '4', '5', '5', '5',
       '2', '8', '4', '1', '1', '6', '7', '3', '6', '6', '1', '2', '2',
       '8', '1', '1', '2', '3', '6', '7', '6', '4', '3', '3', '7', '3',
       '6', '5', '3', '7', '3', '5', '6', '7', '8', '6', '2', '4', '7',
       '3', '6', '3', '3', '7', '1', '6', '6', '8', '6', '4', '5', '3',
       '3', '6', '8', '8', '3', '1', '7', '7', '8', '8', '3', '7', '4',
       '2', '3', '2', '5', '1', '3', '1', '8', '5', '4', '3', '8', '1',
       '1', '2', '5', '2', '2', '5', '1', '2', '4', '3', '4', '2', '7',
       '4', '8', '7', '8', '3', '7', '7', '8', '1', '1', '6', '2', '8',
       '6', '1', '5', '2', '6', '3', '1', '3', '5', '7', '4', '8', '1',
       '8', '1', '7', '5', '3', '7', '5', '5', '8', '6', '2', '6', '4',
       '7', '1', '3', '4', '5', '7', '7', '2', '8', '2', '5', '7', '3',
       '3', '7', '5', '2', '1', '5', '5', '2', '6', '4', '3', '8', '2',
       '8', '5', '8', '8', '1', '2', '4', '4', '1', '8', '2', '5', '5',
       '2', '3', '4', '2', '6', '3', '1', '8', '2', '5', '8', '8', '3',
       '1', '3', '5', '6', '7', '8', '2', '5', '5', '5', '3', '7', '1',
       '5', '6', '5', '4', '3', '5', '8', '7', '2', '7', '2', '2', '1',
       '7', '4', '7', '3', '5', '4', '3', '8', '6', '1', '1', '7', '5',
       '1', '8', '6', '3', '1', '3', '6', '2', '3', '7', '4', '6', '5',
       '7', '1', '6', '4', '5', '6', '2', '2', '6', '7', '3', '1', '7',
       '6', '5', '6', '3', '4', '2', '4', '3', '1', '5', '6', '4', '5',
       '7', '2', '6', '3', '8', '3', '7', '1', '3', '3', '6', '4', '5',
       '3', '5', '4', '7', '4', '2', '5', '7', '4', '6', '8', '6', '6',
       '3'], dtype='<U21')

And I am very certain that random.randint(1,2) gives 1 or 2, so I am confused why there are no changes at all

CodePudding user response:

Your error is that you generated only one value:

>>> '1' if random.randint(1, 2) == 1 else 'A'
'1'

And you use this value to assign to the position where the element in arr is '1'. This will not make 50% of '1' become 'A', but there is a 50% probability that all '1' become 'A'.

The correct way is to generate an array with the length of '1' occurrence times, where '1' and 'A' are randomly generated, and then this array is used for assignment:

>>> mask = arr == '1'
>>> arr[mask] = np.random.default_rng().choice(('1', 'A'), mask.sum())
>>> # The speed of choice is relatively slow. The faster way is
>>> # arr[mask] = np.where(np.random.default_rng().integers(0, 2, mask.sum(), bool))
>>> arr
array(['A', '3', '5', '7', '3', '7', '3', '4', '2', '4', '5', '5', '5',
       '2', '8', '4', '1', '1', '6', '7', '3', '6', '6', 'A', '2', '2',
       '8', 'A', 'A', '2', '3', '6', '7', '6', '4', '3', '3', '7', '3',
       '6', '5', '3', '7', '3', '5', '6', '7', '8', '6', '2', '4', '7',
       '3', '6', '3', '3', '7', 'A', '6', '6', '8', '6', '4', '5', '3',
       '3', '6', '8', '8', '3', '1', '7', '7', '8', '8', '3', '7', '4',
       '2', '3', '2', '5', 'A', '3', 'A', '8', '5', '4', '3', '8', '1',
       'A', '2', '5', '2', '2', '5', '1', '2', '4', '3', '4', '2', '7',
       '4', '8', '7', '8', '3', '7', '7', '8', '1', 'A', '6', '2', '8',
       '6', 'A', '5', '2', '6', '3', '1', '3', '5', '7', '4', '8', '1',
       '8', 'A', '7', '5', '3', '7', '5', '5', '8', '6', '2', '6', '4',
       '7', 'A', '3', '4', '5', '7', '7', '2', '8', '2', '5', '7', '3',
       '3', '7', '5', '2', '1', '5', '5', '2', '6', '4', '3', '8', '2',
       '8', '5', '8', '8', 'A', '2', '4', '4', '1', '8', '2', '5', '5',
       '2', '3', '4', '2', '6', '3', '1', '8', '2', '5', '8', '8', '3',
       '1', '3', '5', '6', '7', '8', '2', '5', '5', '5', '3', '7', '1',
       '5', '6', '5', '4', '3', '5', '8', '7', '2', '7', '2', '2', 'A',
       '7', '4', '7', '3', '5', '4', '3', '8', '6', 'A', '1', '7', '5',
       '1', '8', '6', '3', 'A', '3', '6', '2', '3', '7', '4', '6', '5',
       '7', '1', '6', '4', '5', '6', '2', '2', '6', '7', '3', '1', '7',
       '6', '5', '6', '3', '4', '2', '4', '3', 'A', '5', '6', '4', '5',
       '7', '2', '6', '3', '8', '3', '7', '1', '3', '3', '6', '4', '5',
       '3', '5', '4', '7', '4', '2', '5', '7', '4', '6', '8', '6', '6',
       '3'], dtype='<U21')

CodePudding user response:

Firstly, random.randint should instead be np.random.randint on line 2.

Secondly, if you read the documentation of randint, you will find that the second parameter is one above the largest (signed) integer to be drawn from the distribution. As such, if you want to produce a random integer out of 1 and 2, your implementation should be np.random.randint(1,3).

  • Related