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 l

По сути, мне нужен способ проверить, что вывод - -inf но я не знаю, как поступить. Спасибо за помощь!

Ответы

Ответ 1

Так как log для x=0 минус бесконечный, я просто проверю, является ли входное значение равным нулю и возвращает все, что вы там хотите:

def safe_ln(x):
    if x <= 0:
        return 0
    return math.log(x)

EDIT: небольшое редактирование: вы должны проверить, все ли значения меньше или равны 0.

EDIT 2: np.log - это, конечно, функция для вычисления в массиве numpy, для одиночных значений вы должны использовать math.log. Так выглядит вышеописанная функция с numpy:

def safe_ln(x, minval=0.0000000001):
    return np.log(x.clip(min=minval))

Ответ 2

Вы используете функцию np, поэтому я могу смело предположить, что вы работаете с массивом numpy? Тогда самый эффективный способ сделать это - использовать функцию where вместо цикла 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? если где-то вы должны вернуться к исходному значению, вы столкнетесь с некоторой проблемой, изменив нули на единицы...

Ответ 3

Вы можете сделать это.

def safe_ln(x):
   try:
      l = np.log(x)
   except ZeroDivisionError:
      l = 0
   return l

Ответ 4

использовать обработку исключений:

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

Ответ 5

вы можете сделать:

def safe_ln(x):
    #returns: ln(x) but replaces -inf with 0
    try:
        l = np.log(x)
    except RunTimeWarning:
        l = 0
    return l

Ответ 6

Ответ, данный Энрико, хорош, но оба решения приводят к предупреждению:

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]