Are there ways to change a numpy value by chance?

Question:

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

Asked By: fishbowl1

||

Answers:

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).

Answered By: pproe

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')
Answered By: Mechanic Pig
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.