Pregunta

Estoy haciendo un pyploting de datos genéricos y convertirlo de un valor de potencia a un valor de dB.Debido al sistema del que provienen estos valores, 0 se utiliza como indicador de "los datos útiles terminan aquí" (la naturaleza de las matemáticas, no un valor definido).

Mi forma habitual de lidiar con esto es envolver la conversión en un intento/excepto y devolver un valor "bajo" predeterminado, por ejemplo

def f(value):
    try:
        return convert(value)
    except ValueError:
        return -140 #implementation specific, don't worry

Esto está muy bien para el 90% del uso dentro de mi marco, excepto cuando se trata de gráficos.

Soy vago así que lo que hago en este momento es:

pl.plot(xvals,map(f,yvals))

Esto extrae los datos correctamente y, cuando terminan, se precipita por un precipicio, que es el comportamiento esperado.Pero lo que me gustaría que sucediera es que el gráfico simplemente fin cuando se encuentra con una excepción ValueError y elimina f() por completo.

Aparte de dividir el mapa en un bucle, ¿alguien tuvo alguna idea brillante?

ACTUALIZACIONES:

Estoy usando pylab / matplotlib "Endpoint" es dependiente de la ejecución;A veces lo anterior no importa en absoluto ya que no existen valores "malos".Todo esto es en un esfuerzo por ser vago y usar la escala de gráficos matplotlibs en lugar de restablecer los ylim dinámicos en función del mínimo de ydata (lo cual no hago en cajeros automáticos, solo ylim (-140) en este caso).

Actualización vagamente importante sobre la respuesta:La respuesta de unutbu es lo que realmente usaré para mi implementación, debido a (no mencionado en las dependencias de la pregunta), ya que generar un StopIteration en esta función utilizada regularmente causa estragos en la lógica de control no relacionada con la pregunta, sin poner todo de esas otras instancias en try-excepts;A veces -inf tiene más sentido de lo que piensas.

Gracias a todos por ser increíblemente rápidos y le pido disculpas a unutbu por el QuestionFail.

¿Fue útil?

Solución

Quizás haya algún truco en la biblioteca de trazado, pero, para empezar, parece que una opción mucho mejor no genera dichos datos.No es eso map te ahorra treinta líneas de código...

Usar itertools.takewhile(lambda y: y != NO_VALUE, (f(y) for y in yvals)) (y envolverlo en una llamada a list si la biblioteca de trazado requiere una lista en lugar de un iterable).

Editar:Tuve una idea aún mejor:En el envoltorio, agregue

except ValueError:
    raise StopIteration

Esa es la excepción que indica "fin de iteración", y map lo respeta.

Otros consejos

Si estas usando matplotlib, entonces implica que tienes numpy instalado.

Ya que estás convirtiendo a dB, parece que podrías estar tomando un registro.En ese caso, np.log(0) = -inf.

Puedes enmascarar nans e infs con la función numpy np.ma.masked_invalid, y matplotlib puede trazar matrices enmascaradas.Por ejemplo,

import matplotlib.pyplot as plt
import numpy as np

xvals=np.arange(100)
yvals=np.cumsum(np.random.random(100))
yvals[-10:]=0
yvals=np.log(yvals)

print(yvals[-10:])
# [-Inf -Inf -Inf -Inf -Inf -Inf -Inf -Inf -Inf -Inf]

yvals=np.ma.masked_invalid(yvals)
plt.plot(xvals,yvals)
plt.show()

rendimientosenter image description here

Observe que el gráfico termina con xval igual a 89, ya que los últimos 10 valores de yval están enmascarados.

Te estás limitando innecesariamente al negarte a utilizar una construcción en bucle.

En su situación, desea dejar de iterar sobre los datos cuando se alcanza un cierto valor, ese es exactamente el propósito de forloops y breaks

yvals_ = []
for y in yvals:
    y_ = f(y)
    if y_ == -140:
        break
    else:
        yvals_.append(y_)

p1.plot(xvals[:len(yvals_)],yvals_)

Parece que tienes datos y no quieres trazar el último punto.Entonces, ¿qué tal si no lo planeamos?

pl.plot(xvals[:-1], map(f, yvals)[:-1])
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top