Нахождение значений X в массиве numpy и замена случайного значения - PullRequest
0 голосов
/ 26 января 2020

Рассмотрим список numpy массивов со значениями -1 или 1, расположенными в случайных позициях.

a = np.array([1,-1,1,1,-1,1,-1,-1,1,-1])
b = np.array([-1,-1,1,-1,1,1,-1,1,-1,-1])

Мне нужно выполнить операции над этими массивами, такие как умножение суммы и точки.

Например, после суммирования двух массивов у меня будет новый со значениями -2,0 и 2.

c = a + b
c = [ 0 -2 2 0 0 2 -2 0 0 -2]

Теперь я хотел бы «нормализовать» его обратно к -1 и 1.

Для 2 и -2 это легко:

c[c < 0] = -1

c[c > 0] = 1

Проблема в 0. Для них я хотел бы выбрать случайным образом -1 или 1.

Желаемый результат будет выглядеть следующим образом:

c =  [ 1 -1 1 -1 -1 1 -1 1 -1 -1]

В обобщенных терминах мой вопрос состоит в том, как найти в массиве все N значений, равных x, а затем заменить каждое случайное число.

У меня вопрос, как сделать это самым «питонным» и самым быстрым способом?

Спасибо

Ответы [ 3 ]

1 голос
/ 26 января 2020

Просто опубликовать окончательные результаты из ответов, которые я получил до сих пор. Если у кого-нибудь в будущем будет лучшее решение, поделитесь им!

Я рассчитал 3 решения, которые нашел, и одно, которое я сделал.

def Norm1(HV):
    HV[HV > 0] = 1
    HV[HV < 0] = -1
    zind = np.where(HV == 0)[0]
    HV[zind] = np.array([np.random.choice([1, -1]) for _ in zind])
    return HV

def norm2(HV):
    if HV == 0: 
        return np.random.choice(np.array([-1,1])) 
    else: 
        return HV / HV * np.sign(HV)                                                                         

Norm2 = np.vectorize(norm2)

def Norm3(HV):
    HV[HV > 0] = 1
    HV[HV < 0] = -1
    mask = HV==0;
    HV[mask] = np.random.choice((-1,1),HV[mask].shape)
    return HV

def generate(size):
    return np.random.binomial(1, 0.5, size=size) * 2 - 1

def Norm4(arr):
    np.floor_divide(arr, 2, out=arr)
    positions = (arr == 0)
    size = sum(positions)
    np.add.at(arr, positions, generate(size)

Время было:

%%timeit
d = Norm1(c)
203 µs ± 5.9 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

%%timeit
d = Norm2(c)
33.4 ms ± 1.03 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

%%timeit
d = Norm3(c)
217 µs ± 11.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%%timeit
d = Norm4(c)
21 ms ± 1.23 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

Итак, в нынешнем виде это выглядит как ответ 1 и 3 - лучшие. Разница между ними выглядит минимальной, но после нескольких пробных попыток номер 1 всегда идет немного впереди .

Спасибо за помощь, ребята! Я добавлю некоторые ссылки на HD-вычисления в этом вопросе, так как это основная проблема в этом приложении, поэтому кому-то будет легче найти его, если это необходимо.

0 голосов
/ 26 января 2020

Вы можете использовать:

>>> c = [0, -2, 2, 0, 0, 2, -2, 0, 0, -2]
>>> c = np.array([0, -2, 2, 0, 0, 2, -2, 0, 0, -2])
>>> zind = np.where(c==0)[0]
>>> c[zind] = np.array([np.random.choice([1, -1]) for _ in zind])
>>> c
array([ 1, -2,  2, -1, -1,  2, -2, -1,  1, -2])
0 голосов
/ 26 января 2020

Я не , утверждая, что это самый быстрый и не самый эффективный подход.

c = np.array([ 0, -2, 2, 0, 0, 2, -2, 0, 0, -2])                       

def norm(a): 
    if a == 0: 
        return np.random.choice(np.array([-1,1])) 
    else: 
        return a / a * np.sign(a)                                                                         

v_norm = np.vectorize(norm)
norm_arr = v_norm(c)                                   

Результат:

In [64]: norm_arr                                                             
Out[64]: array([ 1, -1,  1,  1, -1,  1, -1,  1, -1, -1])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...