Python;exceção ciente (mapa)
-
14-11-2019 - |
Pergunta
Estou fazendo algumas pyplotting de dados genéricos e convertê-lo a partir de um valor de energia para um valor de base de dados.Devido ao sistema de estes valores são a partir de, 0 é usado como um 'os dados úteis termina aqui' (indicador da natureza da matemática, não um valor definido).
A minha forma habitual de lidar com essas envolve a conversão em um try/except e retornando um padrão "baixo" valor, por exemplo,
def f(value):
try:
return convert(value)
except ValueError:
return -140 #implementation specific, don't worry
Este é fino e elegante, para 90% de utilização dentro do meu quadro, exceto quando se trata de gráficos.
Eu sou preguiçosa então o que eu faço no momento é:
pl.plot(xvals,map(f,yvals))
Isso atrai os dados corretamente, e quando os dados termina, e precipita-se fora de um penhasco, que é o comportamento esperado.Mas o que eu gostaria de acontecer é para o gráfico, basta fim quando ele encontra uma exceção ValueError e acabar com f() completamente.
Outros que quebrar o mapa em um loop, alguém tem quaisquer idéias brilhantes?
ATUALIZAÇÕES:
Eu estou usando o Pylab / MatplotLib "Ponto final" é a execução dependentes;às vezes, o que não importa atall como não há 'ruim' valores.Isso é tudo em um esforço para eu ser preguiçoso e usar matplotlibs gráfico de escala, em vez de redefinição da dinâmica ylim baseado no min da ydata (que eu não faço atm, apenas ylim(-140), neste caso).
Vagamente Atualização Importante Na Resposta:unutbu, a resposta é que eu vou estar usando para minha implementação, devido a (não mencionado na pergunta dependências), como levantar um StopIteration neste usados regularmente a função de causa estragos alheios-para-o-questão de lógica de controle, sem colocar em todos os outros casos em tentar-excetua;às vezes -inf faz mais sentido do que você imagina.
Obrigado a todos por ser incrivelmente rápido, e eu pedir desculpas para unutbu para o QuestionFail.
Solução
Talvez haja algum truque na biblioteca de plotagem, mas muito melhores opções parece não gerar tais dados para começar.Não é que map
você economiza trinta linhas de código...
Utilização itertools.takewhile(lambda y: y != NO_VALUE, (f(y) for y in yvals))
(e enrole-o em uma chamada para list
se o desenho da biblioteca requer uma lista em vez de um iterable).
Editar:Eu tinha uma idéia ainda melhor:Na embalagem, adicione
except ValueError:
raise StopIteration
Essa é a exceção de sinalização de "fim de iterale", e map
respeita-o.
Outras dicas
Se você estiver usando o matplotlib
, e , em seguida, isso implica que você tem numpy
instalado.
Desde que você está convertendo para dB
, parece que você pode estar tendo um registo.Nesse caso, np.log(0) = -inf
.
Você pode máscara nans e infs com o numpy função np.ma.masked_invalid, e matplotlib
pode enredo mascarado matrizes.Por exemplo,
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()
rendimentos
Observe que o gráfico termina com xval
igual a 89, desde os últimos 10 valores de yval
são mascarados.
Você está desnecessariamente a limitar-se ao recusar-se a usar uma construção de loop.
No seu caso você quer parar de iteração através de dados quando um determinado valor é atingido, que é exatamente o propósito de forloops
e 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 você tem dados, e você não quer desenhar o último ponto.Por que não plotagem-lo?
pl.plot(xvals[:-1], map(f, yvals)[:-1])