python: sortear división por cero
numpy division (6)
¿Está utilizando una función np, así que puedo adivinar con seguridad que está trabajando en una matriz numpy? Entonces la forma más eficiente de hacer esto es usar la función where en lugar de un bucle for
myarray= np.random.randint(10,size=10)
result = np.where(myarray>0, np.log(myarray), 0)
de lo contrario, simplemente puede usar la función de registro y luego parchar el agujero:
myarray= np.random.randint(10,size=10)
result = np.log(myarray)
result[result==-np.inf]=0
La función np.log devuelve correctamente -inf cuando se usa en un valor de 0, ¿está seguro de que desea devolver un 0? Si en algún lugar tiene que volver al valor original, experimentará algún problema, cambiando los ceros por unos ...
Tengo un gran conjunto de datos de números de punto flotante. Repito a través de ellos y evalúo np.log(x)
para cada uno de ellos. yo obtengo
RuntimeWarning: divide by zero encountered in log
Me gustaría evitar esto y devolver 0 si se produce este error.
Estoy pensando en definir una nueva función:
def safe_ln(x):
#returns: ln(x) but replaces -inf with 0
l = np.log(x)
#if l = -inf:
l = 0
return l
Básicamente, necesito una forma de probar que la salida es -inf
pero no sé cómo proceder. ¡Gracias por tu ayuda!
La respuesta dada por Enrico es buena, pero ambas soluciones dan como resultado una advertencia:
RuntimeWarning: divide by zero encountered in log
Como alternativa, podemos seguir usando la función where
, pero solo ejecutar el cálculo principal cuando sea apropiado:
# 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))
Mi caso de uso fue para la división, pero el principio es claramente el mismo:
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]
Podrías hacerlo:
def safe_ln(x):
#returns: ln(x) but replaces -inf with 0
try:
l = np.log(x)
except RunTimeWarning:
l = 0
return l
Puedes hacerlo.
def safe_ln(x):
try:
l = np.log(x)
except ZeroDivisionError:
l = 0
return l
Ya que el log
para x=0
es menos infinito, simplemente verificaría si el valor de entrada es cero y devolvería lo que quieras allí:
def safe_ln(x):
if x <= 0:
return 0
return math.log(x)
EDITAR : edición pequeña: debe verificar todos los valores menores o iguales a 0.
EDIT 2 : np.log
es, por supuesto, una función para calcular en una matriz numpy, para valores únicos debe usar math.log
. Así es como se ve la función anterior con numpy:
def safe_ln(x, minval=0.0000000001):
return np.log(x.clip(min=minval))
usar el manejo de excepciones:
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