python: обойти деление на ноль
у меня есть большой набор данных с плавающей точкой. Я перебираю их и оцениваю np.log (x) для каждого из них. Я получаю
RuntimeWarning: divide by zero encountered in log
Я хотел бы обойти это и вернуться к 0, если эта ошибка произойдет.
Я думаю определить новую функцию:
def safe_ln(x):
#returns: ln(x) but replaces -inf with 0
l = np.log(x)
#if l = -inf:
l = 0
return result
в основном мне нужен способ тестирования того, что выход "- inf", но я не знаю, как продолжить. Спасибо за помощь!
6 ответов
С log
на x=0
минус бесконечен, я бы просто проверил, если входное значение равно нулю и вернуть все, что вы хотите там:
def safe_ln(x):
if x <= 0:
return 0
return math.log(x)
редактировать: small edit: вы должны проверить все значения, меньшие или равные 0.
Изменить 2: np.log
это, конечно, функция для вычисления массива numpy, для одиночных значений вы должны использовать math.log
. Вот как выглядит вышеуказанная функция с numpy:
def safe_ln(x, minval=0.0000000001):
return np.log(x.clip(min=minval))
вы используете функцию np, поэтому я могу с уверенностью предположить, что вы работаете над массивом numpy? Тогда самый эффективный способ сделать это-использовать функцию, где вместо цикла for
myarray= np.random.randint(10,size=10)
result = np.where(myarray>0, np.log(myarray), 0)
в противном случае вы можете просто использовать функцию журнала, а затем латать дыры:
myarray= np.random.randint(10,size=10)
result = np.log(myarray)
result[result==-np.inf]=0
np.функция log возвращает правильно-inf при использовании значения 0, поэтому вы уверены, что хотите вернуть 0? если где-то вам нужно вернуться к исходному значению, вы собираетесь чтобы испытать какую-то проблему, измените нули на единицы...
использовать обработки исключений:
In [27]: def safe_ln(x):
try:
return math.log(x)
except ValueError: # np.log(x) might raise some other error though
return float("-inf")
....:
In [28]: safe_ln(0)
Out[28]: -inf
In [29]: safe_ln(1)
Out[29]: 0.0
In [30]: safe_ln(-100)
Out[30]: -inf
вы могли бы сделать:
def safe_ln(x):
#returns: ln(x) but replaces -inf with 0
try:
l = np.log(x)
except RunTimeWarning:
l = 0
return l
ответ, данный Энрико, хорош, но оба решения приводят к предупреждению:
RuntimeWarning: divide by zero encountered in log
в качестве альтернативы мы все еще можем использовать where
функция, но только выполнить основное вычисление, где это уместно:
# alternative implementation -- a bit more typing but avoids warnings.
loc = np.where(myarray>0)
result2 = np.zeros_like(myarray, dtype=float)
result2[loc] =np.log(myarray[loc])
# answer from Enrico...
myarray= np.random.randint(10,size=10)
result = np.where(myarray>0, np.log(myarray), 0)
# check it is giving right solution:
print(np.allclose(result, result2))
мой вариант использования был для разделения, но принцип явно тот же:
x = np.random.randint(10, size=10)
divisor = np.ones(10,)
divisor[3] = 0 # make one divisor invalid
y = np.zeros_like(divisor, dtype=float)
loc = np.where(divisor>0) # (or !=0 if your data could have -ve values)
y[loc] = x[loc] / divisor[loc]