Python;异常感知映射()

发布于 2024-10-28 07:34:54 字数 909 浏览 1 评论 0 原文

我正在对通用数据进行一些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 异常时结束并完全取消 f() 。

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

更新:

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

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

感谢大家的快速反应,我为问题失败向 unutbu 表示歉意。

I'm doing some pyplotting of generic data and converting it from a power value to a dB value. Due to the system these values come from, 0 is used as a 'the useful data ends here' indicator (the nature of the mathematics, not a defined value).

My usual way of dealing with these is wrapping the conversion in a try/except and returning a default 'low' value, eg

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

This is fine and dandy for 90% of use within my framework, except when it comes to graphing.

I'm lazy so what I do at the minute is:

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

This draws the data correctly, and when the data ends, plunges off a cliff, which is the expected behaviour. But what I would like to happen is for the graph to just end when it meets a ValueError exception and do away with f() altogether.

Other than breaking the map up into a loop, anyone got any brilliant ideas?

UPDATES:

I'm using Pylab / MatplotLib
"Endpoint" is execution dependent; sometimes the above doesn't matter atall as there are no 'bad' values. This is all in an effort for me to be lazy and use matplotlibs graph scaling instead of resetting dynamic ylim's based on the min of the ydata (which I don't do atm, just ylim(-140) in this case.)

Vaguely Important Update On Answer:
unutbu's answer is what I'll actually be using for my implementation, due to (not mentioned in the question dependencies), as raising a StopIteration in this regularly used function wreaks havoc with unrelated-to-the-question control logic, without putting all of those other instances in try-excepts; sometimes -inf makes more sense than you would think.

Thanks to everyone for being awesomely fast, and I apologise to unutbu for the QuestionFail.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

滴情不沾 2024-11-04 07:34:54

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

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

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

except ValueError:
    raise StopIteration

That's 异常信号“迭代结束”,并且 map 尊重它。

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.

以酷 2024-11-04 07:34:54

如果您使用的是matplotlib,那么这意味着您已经安装了numpy

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

您可以使用 numpy 函数 np.ma.masked_invalidmatplotlib 可以绘制屏蔽数组。例如,

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 结尾,因为最后 10 个yval 的值被屏蔽。

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.

醉酒的小男人 2024-11-04 07:34:54

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

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

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

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

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_)
为你拒绝所有暧昧 2024-11-04 07:34:54

似乎您有数据,但不想绘制最后一点。那么不画图又如何呢?

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

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])
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文