我需要根据具有随机数的条件替换numpy数组中的某些值。
我有一个在50%的时间内添加随机值的函数:
def add_noise(noise_factor=0.5):
chance = random.randint(1,100)
threshold_prob = noise_factor * 100.
if chance <= threshold_prob:
noise = float(np.random.randint(1,100))
else:
noise = 0.
return(noise)
但是当我调用numpy函数时,它会用生成的随机数替换所有匹配的值:
np.place(X, X==0., add_noise(0.5))
这个问题是add_noise()只运行一次,它用噪声值替换所有0.值。
我想要做的是“迭代”numpy数组中的每个元素,检查条件(是= = 0。)并且我想每次通过add_noise()生成噪声值。
我可以使用for循环遍历每一行和每列,但有没有人知道更有效的方式呢?
答案 0 :(得分:1)
这是一种矢量化方法 -
noise_factor = 0.5 # Input param
# Get mask of zero places and the count of it. Also compute threshold
mask = X==0
c = np.count_nonzero(mask)
threshold_prob = noise_factor * 100.
# Generate noise numbers for count number of times.
# This is where vectorization comes into the play.
nums = np.random.randint(1,100, c)
# Finally piece of the vectorization comes through replacing that IF-ELSE
# with np,where that does the same op of choosing but in a vectorized way
vals = np.where(nums <= threshold_prob, np.random.randint(1,100, c) , 0)
# Assign back into X
X[mask] = vals
其他好处是,我们会重新使用mask
0s
进行add_noise
操作,并将其重新分配回X
。这取代了np.place
的使用,是一种效率标准。
进一步提升绩效
我们可以在计算nums
和vals
的步骤中进一步优化,这些步骤使用两个随机数生成步骤代替一次,然后在第二步重新使用,就像这样 -
nums = np.random.randint(1,100, (2,c))
vals = np.where(nums[0] <= threshold_prob, nums[1] , 0)
答案 1 :(得分:0)
你可以对你的函数进行矢量化,这样可以很容易地应用到每个元素,并且我认为它也非常有效。
import random
import numpy as np
def add_noise(x):
if not x:
if random.random() <= 0.5:
noise = float(np.random.randint(1,100))
return noise
else:
return 0
else:
return x
x = np.zeros(shape=(10, 10))
n = np.vectorize(add_noise)
x = n(x)
答案 2 :(得分:0)
如果我理解正确,您希望根据两个条件将numpy数组的值更改为随机值。
对于这两个条件,您可以创建两个蒙版并将它们与np.logical_and
合并。您可以使用np.random
方法获取随机数组。
import numpy as np
def add_perhaps_noise_if_zero(x, threshold=0.5):
mask_1 = x == 0.0
mask_2 = np.random.random(x.shape) <= threshold
mask_combined = np.logical_and(mask_1, mask_2)
x[mask_combined] += np.random.random(x.shape)[mask_combined]
return x
x = np.zeros((5,5))
for i in range(5):
print(x)
x = add_perhaps_noise_if_zero(x)