Предупреждение о неожиданном делении на ноль при использовании np.where - PullRequest
1 голос
/ 25 мая 2020

Я новичок в numpy и пытаюсь заменить циклы for, используя np.where. То, что я пытаюсь достичь, просто: у меня есть 4 разных условия, и на основе этих условий я присваиваю значения элементам массива:

Period = np.arange(0.0,8.0,0.01)

Ta = 0.075
Tb = 0.375
Tl = 6.0
Sds = 1.2
Sd1 = 0.45

Sae = np.zeros(len(Period))
Sae = np.where((Period>=0.0) & (Period<=Ta),0.4+0.6*(Period/Ta)*Sds,Sae)
Sae = np.where((Period>=Ta) & (Period<=Tb),Sds,Sae)
Sae = np.where((Period>=Tb) & (Period<=Tl),Sd1/Period,Sae)
Sae = np.where((Period>=Tl),Sd1*Tl/Period**2,Sae)

И получаю RuntimeWarning:

RuntimeWarning: divide by zero encountered in true_divide
  Sae = np.where((Period>=Tb) & (Period<=Tl),Sd1/Period,Sae)
RuntimeWarning: divide by zero encountered in true_divide
  Sae = np.where((Period>=Tl),Sd1*Tl/Period**2,Sae)

Я знаю, что массив Period начинается с 0,0, но наложенные условия должны избегать деления на ноль.

Однако в результирующем массиве Sae нет ничего плохого. Тем не менее, я бы не хотел видеть предупреждение о делении на ноль.

Спасибо!

Ответы [ 2 ]

3 голосов
/ 25 мая 2020

Проблема в том, что arr1 / arr2 оценивается перед вызовом np.where(), поэтому NumPy мудро предупреждает вас о потенциальной проблеме.

Если вы абсолютно уверены, что ваше предупреждение не применяется для вас, вы можете просто игнорировать его для строки (ов) виновника, например:

with numpy.errstate(divide='ignore'):
    # The problematic line(s)
    Sae = np.where((Period>=Tl),Sd1*Tl/Period**2,Sae)
    ...

Подробнее об этом здесь .

В качестве альтернативы вы можете просто избежать разделения нулем с соответствующей маской. Например, эта строка:

Sae = np.where((Period>=Tl),Sd1*Tl/Period**2,Sae)

будет выглядеть так:

mask = Period > 0
temp = np.zeros_like(Period)
temp[mask] = Sd1*Tl/Period[mask]**2
Sae = np.where((Period>=Tl),temp,Sae)
1 голос
/ 25 мая 2020
Sae = np.where((Period>=Tb) & (Period<=Tl), Sd1/Period, Sae)

эквивалентно

if_mask = (Period>=Tb) & (Period<=Tl)
then = Sd1/Period
else_ = Sae
Sae = np.where(if_mask, then, else_)

Вы делите на ноль в Sd1/Period, потому что первый элемент Period равен 0.0.

...