【问题标题】:Python; exception aware map()Python;异常感知 map()
【发布时间】:2011-07-26 06:09:37
【问题描述】:

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

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

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

这对于我的框架中 90% 的使用来说都很好,除了在绘图方面。

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

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

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

除了将地图分解成一个循环之外,还有人有什么绝妙的想法吗?

更新:

我正在使用 Pylab / MatplotLib “端点”取决于执行;有时上述内容根本不重要,因为没有“坏”值。这一切都是为了让我变得懒惰并使用matplotlibs图形缩放而不是根据ydata的最小值重置动态ylim(我不做atm,在这种情况下只是ylim(-140)。)

关于答案的模糊重要更新: unutbu 的答案是我实际上将用于我的实现的,因为(在问题依赖项中没有提到),因为在这个经常使用的函数中引发 StopIteration 会对与问题无关的控制逻辑造成严重破坏,而不是把所有try-excepts 中的其他实例;有时 -inf 比你想象的更有意义。

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

【问题讨论】:

  • 这个问题有点不清楚。如果你把地图分解成一个循环,你能展示一下它会是什么样子吗?

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


【解决方案1】:

如果您使用的是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()

产量

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

【讨论】:

  • 在这种情况下它的 log10 但我喜欢它的发展方向。将调查和更新(除非你或其他任何人比我更早!)
  • 我实际上是在使用你的答案,但严格来说,我的剥离其他依赖项的问题已通过 StopIteration 响应得到了回答。
  • 不用担心;很高兴你找到了答案。
【解决方案2】:

拒绝使用循环结构是在不必要地限制自己。

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

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

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

【讨论】:

    【解决方案3】:

    也许绘图库中有一些技巧,但更好的选择似乎一开始就不会生成此类数据。不是map为你省了三十行代码……

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

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

    except ValueError:
        raise StopIteration
    

    这是表示“迭代结束”的异常信号,map 尊重它。

    【讨论】:

    • 关于旧解决方案的说明,imap() 是 map() 的迭代器版本,因此无需遍历所有数据即可使用 takewhile。但是需要最新的 Python 版本。
    • @Gustav Larsson: map 是列出推导式,就像 imap 是生成器表达式一样。我尽可能使用生成器表达式,包括这里。
    【解决方案4】:

    您似乎有数据,并且您不想绘制最后一点。那么不绘制呢?

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

    【讨论】:

    • 这只会切断最后一项。 OP 是否声明它始终只是包含虚假数据的最后一项?
    • @delnan:这就是我所理解的:“这会正确绘制数据,并且当数据结束时,会从悬崖上掉下来”。如果它并不总是最后一项,那么您的方法将是合适的
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-11
    • 2015-12-23
    • 1970-01-01
    • 1970-01-01
    • 2010-10-28
    相关资源
    最近更新 更多