用随机数替换条件上的numpy数组值

时间:2017-02-28 19:42:12

标签: python arrays numpy random vectorization

我需要根据具有随机数的条件替换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循环遍历每一行和每列,但有没有人知道更有效的方式呢?

3 个答案:

答案 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的使用,是一种效率标准。

进一步提升绩效

我们可以在计算numsvals的步骤中进一步优化,这些步骤使用两个随机数生成步骤代替一次,然后在第二步重新使用,就像这样 -

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数组的值更改为随机值。

  1. 值应为零
  2. 一些随机机会因素
  3. 对于这两个条件,您可以创建两个蒙版并将它们与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)