Python;异常感知映射()
-
14-11-2019 - |
题
我正在做一些通用数据,并将其从电源值转换为db值。由于系统,这些值来自0,0用作“这里的有用数据”指示符(数学的性质,而不是定义的值)。
我通常的处理这些方式是在尝试/之外包装转换,并返回默认的“低”值,例如
.
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()。
除了将地图打成一个循环,任何人都有任何辉煌的想法?
更新:
我正在使用pylab / matplotlib “端点”依赖于执行;有时以上并不重要,因为没有“坏”值。这一切都努力让我懒惰,并使用Matplotlibs图表缩放而不是基于YDATA的最小值(我不做ATM,在这种情况下只能重置动态Ylim。)
答案上模糊的重要更新: Unutbu的答案是我实际使用的是我的实现,因为(问题依赖性未提及),因为在这个定期使用的函数中提高了一个缺陷的函数造成的不相关到逻辑的逻辑,而不会使所有其他实例在预防之外;有时-inf会比你想象的更有意义。
感谢每个人都令人敬畏,我向Unutbu道歉的问号。
解决方案
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.
其他提示
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
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])