Domanda

Sto facendo un po 'di pyplotting di dati generici e convertendolo da un valore di potenza a un valore DB. A causa del sistema viene da cui questi valori provengono, 0 è usato come un indicatore "I dati utili termina qui" (la natura della matematica, non un valore definito).

Il mio solito modo di affrontare questi sta avvolgendo la conversione in un tentativo / tranne e restituire un valore "basso" predefinito, ad esempio

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

Questo va bene e dandy per il 90% dell'uso nel mio quadro, tranne quando si tratta di grafico.

Sono pigro, quindi quello che faccio al minuto è:

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

Questo disegna correttamente i dati e quando finisce i dati, si tuffa una scogliera, che è il comportamento previsto. Ma quello che vorrei accadere è per il grafico a solo fine quando incontra un'eccezione di ValueError e fai via con f () del tutto.

Oltre a rompere la mappa in un ciclo, chiunque abbia delle idee brillanti?

Aggiornamenti:

Sto usando pylab / matplotlib "Endpoint" dipende dall'esecuzione; A volte sopra non importa come non ci sono valori "cattivi". Questo è tutto in uno sforzo per me per essere pigro e usare il ridimensionamento del grafico dei matplotlibs invece di reimpostare gli yfini dinamici basati sul minimo del YData (che non faccio ATM, solo Ylim (-140) in questo caso.) .

Aggiornamento vagamente importante sulla risposta: La risposta di Unutbu è ciò che utilizzerò effettivamente per la mia attuazione, a causa del (non menzionato nelle dipendenze delle domande), poiché l'aumento di una stopiterazione in questa funzione regolarmente utilizzata devastare la logica di controllo non correlata alla domanda, senza mettere tutto di quegli altri casi in prova; A volte -inf ha più senso di quanto pensassi.

Grazie a tutti per essere stato awesomely e mi scuso con UNATBU per il Domanda.

È stato utile?

Soluzione

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.

Altri suggerimenti

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])
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top