Question

Je fais du pyplotting des données génériques et de la convertir d'une valeur de puissance en une valeur de dB. En raison du système, ces valeurs proviennent, 0 est utilisée comme indicateur "Les données utiles ici" (la nature des mathématiques, pas une valeur définie).

Ma façon habituelle de traiter avec celles-ci est en train d'envelopper la conversion en essayant / sauf et de retourner une valeur «basse» par défaut, par exemple

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

C'est bon et dandy pour 90% d'une utilisation dans mon cadre, sauf en ce qui concerne le graphique.

Je suis paresseux alors ce que je fais à la minute est:

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

Ceci dessine correctement les données et lorsque les données se termine, plongeant une falaise, qui est le comportement attendu. Mais ce que j'aimerais arriver, c'est que le graphique soit juste finalement quand il rencontre une exception de ValueError et élimine complètement avec F ().

Autre que briser la carte dans une boucle, tout le monde a obtenu des idées brillantes?

mises à jour:

J'utilise pylab / matplotlib "Terminal" est dépendant de l'exécution; Parfois, ce qui précède n'a pas d'importance, car il n'y a pas de valeurs «mauvaises». C'est tout dans un effort pour moi d'être paresseux et d'utiliser Matplotlibs graphique à la mise à l'échelle au lieu de réinitialiser les YLIM dynamiques basé sur la minute de l'ydata (que je ne fais pas ATM, juste Ylim (-140) dans ce cas.)

Mise à jour vaguement importante sur la réponse: La réponse de tsutbu est ce que j'aurai réellement utiliser pour ma mise en œuvre, en raison de (non mentionné dans les dépendances de la question), comme élever une stariterie dans cette fonction régulièrement utilisée gagne des ravages avec une logique de contrôle non liée à la question, sans mettre tout de ces autres cas en essayant-sauf; parfois -inf a plus de sens que vous ne le pensez.

Merci à tout le monde pour être rapide, et je m'excuse à Outbu pour le questionnaire.

Était-ce utile?

La solution

Perhaps there's some trick in the plotting library, but a much better options seems not generating such data to begin with. It's not that map saves you thirty lines of code...

Use itertools.takewhile(lambda y: y != NO_VALUE, (f(y) for y in yvals)) (and wrap it in a call to list if the plotting library requires a list instead of an iterable).

Edit: I had an even better idea: In the wrapper, add

except ValueError:
    raise StopIteration

That's the exception signaling "end of iterale", and map respects it.

Autres conseils

If you are using matplotlib, then it implies you have numpy installed.

Since you are converting to dB, it sounds like you might be taking a log. In that case, np.log(0) = -inf.

You can mask nans and infs with the numpy function np.ma.masked_invalid, and matplotlib can plot masked arrays. For example,

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()

yields enter image description here

Notice that the graph ends with xval equal to 89, since the last 10 values of yval are masked.

You're needlessly limiting yourself by refusing to use a looping construct.

In your situation you want to stop iterating over data when a certain value is reached, that is exactly the purpose of forloops and breaks

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

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

It seems like you have data, and you don't want to plot the last point. So what about not plotting it?

pl.plot(xvals[:-1], map(f, yvals)[:-1])
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top