I have a 2D NumPy array in which I would like to randomly replace a few data points with different values. How do to do that for a general NumPy 2D array?
Example: Randomly replace 6 data elements of A having value 1 with value 2.
Input-
A = [
[1,1,1,1,1,0,0,1,1],
[1,0,1,0,1,1,0,1,1],
[0,1,1,1,1,1,1,1,0],
[1,1,1,1,1,0,0,1,1],
[1,1,0,0,1,0,0,1,1],
[1,1,1,1,1,0,0,1,1],
]
Output-
A'= [
[1,1,1,2,1,0,0,1,2],
[1,0,1,0,1,1,0,1,1],
[0,1,1,1,1,1,1,1,0],
[1,1,1,2,1,0,0,1,1],
[1,1,0,0,1,0,0,1,2],
[2,1,1,1,1,0,0,1,2],
]
How to achieve this using Numpy with few lines of code? Any help would be appreciated.
CodePudding user response:
You can get a random position of an element in your array and, if the value is 1, replace it with 2.
Here an example:
from random import randint
A = [
[1,1,1,1,1,0,0,1,1],
[1,0,1,0,1,1,0,1,1],
[0,1,1,1,1,1,1,1,0],
[1,1,1,1,1,0,0,1,1],
[1,1,0,0,1,0,0,1,1],
[1,1,1,1,1,0,0,1,1],
]
arrayLenght = len(A)
rowLenght = len(A[0])
for _ in range(6):
y = randint(0,arrayLenght-1)
x = randint(0,rowLenght-1)
while A[y][x] != 1:
y = randint(0,arrayLenght-1)
x = randint(0,rowLenght-1)
A[y][x] = 2
print(A)
CodePudding user response:
So, break up what you are asking for into several steps. First, get the x and y coordinates where A has the value of 1:
>>> import numpy as np
>>> A = np.array([
... [1,1,1,1,1,0,0,1,1],
... [1,0,1,0,1,1,0,1,1],
... [0,1,1,1,1,1,1,1,0],
... [1,1,1,1,1,0,0,1,1],
... [1,1,0,0,1,0,0,1,1],
... [1,1,1,1,1,0,0,1,1],
... ])
>>> x, y = np.where(A == 1)
>>> x
array([0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3,
3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5])
>>> y
array([0, 1, 2, 3, 4, 7, 8, 0, 2, 4, 5, 7, 8, 1, 2, 3, 4, 5, 6, 7, 0, 1,
2, 3, 4, 7, 8, 0, 1, 4, 7, 8, 0, 1, 2, 3, 4, 7, 8])
Then, randomly sample from these coordinates. We'll accomplish this by selecting a random sample of the indices of the indices:
>>> random_idx = np.random.choice(np.arange(len(x)), 6)
>>> random_idx
array([31, 24, 38, 14, 10, 17])
Then, use this to do a bulk assignment to the value 2 at those indices:
>>> A
array([[1, 1, 1, 1, 1, 0, 0, 1, 1],
[1, 0, 1, 0, 1, 1, 0, 1, 1],
[0, 1, 1, 1, 1, 1, 1, 1, 0],
[1, 1, 1, 1, 1, 0, 0, 1, 1],
[1, 1, 0, 0, 1, 0, 0, 1, 1],
[1, 1, 1, 1, 1, 0, 0, 1, 1]])
>>> A[x[random_idx], y[random_idx]] = 2
>>> A
array([[1, 1, 1, 1, 1, 0, 0, 1, 1],
[1, 0, 1, 0, 1, 2, 0, 1, 1],
[0, 1, 2, 1, 1, 2, 1, 1, 0],
[1, 1, 1, 1, 2, 0, 0, 1, 1],
[1, 1, 0, 0, 1, 0, 0, 1, 2],
[1, 1, 1, 1, 1, 0, 0, 1, 2]])
So, all in one:
import numpy as np
A = np.array([
[1,1,1,1,1,0,0,1,1],
[1,0,1,0,1,1,0,1,1],
[0,1,1,1,1,1,1,1,0],
[1,1,1,1,1,0,0,1,1],
[1,1,0,0,1,0,0,1,1],
[1,1,1,1,1,0,0,1,1],
])
x, y = np.where(A == 1)
random_idx = np.random.choice(np.arange(len(x)), 6)
A[x[random_idx], y[random_idx]] = 2
CodePudding user response:
I think this is the solution you were looking for.
Use size
to get the number of elements in the array.
Use A.item(position)
to get the value in a position.
Use A.itemset(posizione, value)
to set value in position.
Here the code:
from random import randint
from numpy import *
A = matrix([
[1,1,1,1,1,0,0,1,1],
[1,0,1,0,1,1,0,1,1],
[0,1,1,1,1,1,1,1,0],
[1,1,1,1,1,0,0,1,1],
[1,1,0,0,1,0,0,1,1],
[1,1,1,1,1,0,0,1,1],
])
s = size(A)
for _ in range(6):
position = randint(0,s)
while A.item(position) != 1:
position = randint(0,s)
A.itemset(position,2)
print(A)
Important: the array must me matrix
for it to work.