我想做这个人做过的事:
Python - count sign changes
然而,我需要优化它运行超快。简而言之,我想采取一个时间序列,并告诉每一次它交叉过零(改变符号)。我想记录零交叉之间的时间。因为这是真实的数据(32位浮点数)我怀疑我会有一个完全为零的数字,所以这并不重要。我现在有一个计时程序,所以我会计时你的结果,看看谁赢了。
我的解决方案给出(微秒):
open data 8384
sign data 8123
zcd data 415466
正如你所看到的,过零检测器是慢的部分。
import numpy, datetime
class timer():
def __init__(self):
self.t0 = datetime.datetime.now()
self.t = datetime.datetime.now()
def __call__(self,text='unknown'):
print text,'\t',(datetime.datetime.now()-self.t).microseconds
self.t=datetime.datetime.now()
def zcd(data,t):
sign_array=numpy.sign(data)
t('sign data')
out=[]
current = sign_array[0]
count=0
for i in sign_array[1:]:
if i!=current:
out.append(count)
current=i
count=0
else: count+=1
t('zcd data')
return out
def main():
t = timer()
data = numpy.fromfile('deci.dat',dtype=numpy.float32)
t('open data')
zcd(data,t)
if __name__=='__main__':
main()
7条答案
按热度按时间blmhpbnm1#
关于:
输出:
也就是说,zero_crossings将包含发生零交叉的元素 before 的索引。如果你想要 after 的元素,只需向该数组添加1。
mspsb9vt2#
正如Jay Borseth所说,接受的答案不能正确处理包含0的数组。
我建议使用:
因为a)使用numpy.signbit()比numpy.sign()快一点,因为它的实现更简单,我猜b)它正确处理输入数组中的零。
但有一个缺点,也许:如果你的输入数组以零开始和停止,它将在开始处找到一个零交叉,但在结束处没有。
sczxawaw3#
另一种计算零交叉并从代码中挤出几毫秒的方法是使用
nonzero
并直接计算符号。假设你有一个data
的一维数组:或者,如果你只想计算过零点的特定方向(例如,从正到负)的过零点,这甚至更快:
在我的机器上,这些方法比
where(diff(sign))
方法(包含20个周期,总共40个交叉点的10000个正弦样本的数组的计时)快一点:13z8s7eq4#
如果a包含值0,则Jim Brissom的答案失败:
输出:
零交叉的数量应该是7,但是因为如果传递0,sign()返回0,1表示正值,-1表示负值,所以diff()将对包含零的转换计数两次。
另一种可能是:
其给予的正确答案为:
2uluyalo5#
另一种可能适合某些应用程序的方法是扩展表达式
np.diff(np.sign(a))
的求值。如果我们比较这个表达式在某些情况下的React:
1.上升无零交叉:
np.diff(np.sign([-10, 10]))
返回array([2])
1.上升过零:
np.diff(np.sign([-10, 0, 10]))
返回array([1, 1])
1.无零点落交:
np.diff(np.sign([10, -10]))
返回array([-2])
1.落零交叉:
np.diff(np.sign([10, 0, -10]))
返回array([-1, -1])
因此,我们必须为1.和2.中返回的模式计算
np.diff(...)
:以及对于情况3和4:
在此之后,我们可以很容易地找到索引
这种方法应该是合理的快,因为它可以管理,而不使用“慢”循环。
这结合了其他几个答案的方法。
roqulrg36#
我看到人们在他们的解决方案中使用了很多diff,但xor似乎更快,结果对于bools是一样的(一个很好的指针也可能是使用diff给出了一个不推荐的警告...:))这里有一个例子:
timeit
测量它对我来说比diff快一点半:)如果您不关心边缘情况,那么使用
但是positive = a2〉0看起来比signbit AND检查0更快(并且更干净)(例如positive = np.bitwise_or(np.signbit(a2),np.logical_not(a2))更慢...)
9nvpjoqh7#
使用移位数组的元素乘法应该是最快的: