蟒蛇;异常识别地图()

时间:2011-03-30 16:50:54

标签: python exception exception-handling functional-programming map-function

我正在对通用数据进行一些pyplotting,并将其从功率值转换为dB值。由于这些值来自系统,因此0用作“此处有用数据结束”指标(数学的性质,而不是定义的值)。

我处理这些问题的常用方法是在try / except中包含转换并返回默认的“low”值,例如

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

对于我的框架中90%的使用情况,这很好,很花哨,除了图形。

我很懒,所以我现在做的是:

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

这会正确地绘制数据,当数据结束时,会从悬崖上掉下来,这是预期的行为。但我想要的是,当图表遇到ValueError异常并完全取消f()时,图表只是 end

除了将地图分成一个循环之外,还有人有什么好主意吗?

更新

我正在使用Pylab / MatplotLib “端点”依赖于执行;有时上述并不重要,因为没有“坏”值。这一切都是为了让我懒惰并使用matplotlibs图缩放而不是基于ydata的min(我不做atm,在这种情况下只是ylim(-140))重置动态ylim。)

答案的重要更新: unutbu的答案就是我实际上将用于实现的内容,因为(在问题依赖项中没有提到),因为在这个经常使用的函数中引发StopIteration会对不相关的问题控制逻辑造成严重破坏,而不是全部尝试例外的其他情况;有时候-inf比你想象的更有意义。

感谢大家的速度非常快,我为在QuestionFail的unutbu道歉。

4 个答案:

答案 0 :(得分:10)

也许在绘图库中有一些技巧,但更好的选择似乎不会产生这样的数据。这并不是map为您节省了三十行代码......

使用itertools.takewhile(lambda y: y != NO_VALUE, (f(y) for y in yvals))(如果绘图库需要列表而不是可迭代的话,请将其包装在list的调用中。)

编辑:我有一个更好的主意:在包装器中添加

except ValueError:
    raise StopIteration

这是异常信号“iterale结束”,map尊重它。

答案 1 :(得分:2)

如果您使用matplotlib,则表示您已安装numpy

由于您要转换为dB,听起来您可能正在记录日志。在这种情况下,np.log(0) = -inf

您可以使用numpy函数np.ma.masked_invalid屏蔽nans和infs,matplotlib可以绘制屏蔽数组。例如,

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

的产率 enter image description here

请注意,图表以xval等于89结尾,因为yval的最后10个值被屏蔽。

答案 2 :(得分:1)

你不必通过拒绝使用循环结构来限制自己。

在您的情况下,您希望在达到某个值时停止迭代数据,这正是forloopsbreaks

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

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

答案 3 :(得分:0)

好像你有数据,而且你不想绘制最后一点。那么不绘制它呢?

pl.plot(xvals[:-1], map(f, yvals)[:-1])