применяя поэлементное правило при выполнении простой вещательной операции - PullRequest
0 голосов
/ 09 мая 2019

Я хочу умножить два числовых числовых объекта t и speed, не зная априори, является ли каждый из них скалярным или массивом. Проблема в том, что 0 является допустимым значением для t (или для элементов t), а inf является допустимым значением для speed (или для элементов speed). Модель, с которой я работаю, имеет правило для этого случая: где скорость бесконечна, а t равен нулю, произведение определяется как 0.

Моя проблема в том, чтобы применить правило, справляясь с возможными скалярными-возможно-не-нессессиями обоих операндов. Пока лучшее, что я могу придумать, это этот уродливый каскад:

if t.size == 1:
    if t.flat[0]:
        t = t * speed
else:
    nonzero = t != 0
    if speed.size == 1:
        t[nonzero] *= speed
    else:
        t[nonzero] *= speed[nonzero]

Я не могу не думать, что должен быть более эффективный, более Numpythonic способ, которого я скучаю. Есть ли?

Ответы [ 2 ]

1 голос
/ 09 мая 2019

0 * np.inf бросает RuntimeWarning и оценивает np.nan Как насчет простого умножения и замены np.nan после этого?

import numpy as np

def multiply(a, b):
    temp = np.array(a*b)
    temp[np.isnan(temp)] = 0
    return temp

Тестирование:

np.random.seed(123)
t = np.random.rand(10)
t[0] = 0
speed = np.random.rand(10)
speed[0] = np.inf
speed[6] = np.inf

ввод:

multiply(t, speed)

выход:

array([ 0.        ,  0.09201602,  0.02440781,  0.49796297,  0.06170694,
    0.57372377,         inf,  0.03658583,  0.53141369,  0.1746193 ])
0 голосов
/ 12 мая 2019

Прошло пару дней, и никто не написал ответ, данный в комментариях hpaulj и SubhaneilLahiri, поэтому мне лучше сделать это самому.Моя причина для принятия этого принятого ответа заключается в том, что он достаточно общий, чтобы указывать название вопроса, даже в случаях, выходящих за рамки конкретной модели, приведенной в вопросе.

# prepare zeros of the correct shape:
out = np.zeros(np.broadcast(t, speed).shape), dtype=float)

# write the product values into the prepared array, but ONLY
# according to the mask t!=0 
np.multiply(t, speed, where=t!=0, out=out)

В конкретной модели в вопросепредварительно подготовленное значение по умолчанию, равное 0, уже является правильным для всех мест, в которых тест t!=0 не проходит: 0 * speed равен 0 в любом случае, где speed конечен, и это также 0 по указанию (согласнок правилу модели), когда speed бесконечно.Но этот подход можно адаптировать к более общему случаю: в принципе, можно было бы использовать дополнительные пустые вызовы ufunc для заполнения замаскированных частей выходного массива с результатами произвольно различных правил.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...