Python 快速找到非零间隔
我正在写一个算法来确定密度图上“山脉”的间隔。如果有人感兴趣,该图是从Kinect的深处拍摄的。下面是这个算法发现的一个快速可视化示例:(移除小山): 我当前的算法:Python 快速找到非零间隔,python,optimization,numpy,scipy,signal-processing,Python,Optimization,Numpy,Scipy,Signal Processing,我正在写一个算法来确定密度图上“山脉”的间隔。如果有人感兴趣,该图是从Kinect的深处拍摄的。下面是这个算法发现的一个快速可视化示例:(移除小山): 我当前的算法: def find_peak_intervals(data): previous = 0 peak = False ranges = [] begin_range = 0 end_range = 0 for current in xrange(len(data)):
def find_peak_intervals(data):
previous = 0
peak = False
ranges = []
begin_range = 0
end_range = 0
for current in xrange(len(data)):
if (not peak) and ((data[current] - data[previous]) > 0):
peak = True
begin_range = current
if peak and (data[current] == 0):
peak = False
end_range = current
ranges.append((begin_range, end_range))
previous = current
return np.array(ranges)
这个功能可以正常工作,但在我的笔记本电脑上几乎需要3毫秒,我需要能够每秒至少运行30帧的整个程序。这个函数相当难看,我的程序每帧必须运行它3次,因此我想知道如何简化和优化这个函数的提示(可能是我错过的numpy或scipy中的一些内容)。假设像这样的数据帧:
Value
0 0
1 3
2 2
3 2
4 1
5 2
6 3
7 0
8 1
9 3
10 0
11 0
12 0
13 1
14 0
15 3
16 2
17 3
18 1
19 0
您可以使用df[“Value”]获得连续的非零范围。shift(x)
其中x
可以是1
或-1
,因此您可以检查它是否以零为界。一旦获得边界,就可以存储它们的索引对,并在以后过滤数据时使用它们
以下代码基于
结果如下:
1 3
2 2
3 2
4 1
5 2
6 3
Name: Value, dtype: int64
8 1
9 3
Name: Value, dtype: int64
13 1
Name: Value, dtype: int64
15 3
16 2
17 3
18 1
Name: Value, dtype: int64
在IPython中对其进行计时可得出以下结果:
%timeit find_peak_intervals(df)
1000 loops, best of 3: 1.49 ms per loop
这与您的速度尝试相差不远。另一种方法是使用将pandas
系列转换为numpy
阵列并从那里进行操作。让我们以@Warren Weckesser的这篇文章为例,对其进行修改以满足您的需要。我们也来计时吧
In [22]: np_arr = np.array(df["Value"])
In [23]: def greater_than_zero(a):
...: isntzero = np.concatenate(([0], np.greater(a, 0).view(np.int8), [0]))
...: absdiff = np.abs(np.diff(isntzero))
...: ranges = np.where(absdiff == 1)[0].reshape(-1, 2)
...: return ranges
In [24]: %timeit greater_than_zero(np_arr)
100000 loops, best of 3: 17.1 µs per loop
在17.1微秒时还不错,它也给出了相同的范围
[1 7] # Basically same as indices 1-6 in pandas.
[ 8 10] # 8, 9
[13 14] # 13, 13
[15 19] # 15, 18
看起来这个算法主要是一个寻零器。一旦找到一个非零元素,它就会停止比较连续的元素,并再次查找零。因此更像是“if peak and(data[current]==0:”后跟“elif(not peak)and(data[current]!=0:”?谢谢!这两种方法都非常有效。我的数据已经是numpy格式,所以你的第二种方法非常适合。时间从我的系统上的3毫秒(我知道我有一个potatoe)减少到了.21毫秒。
[1 7] # Basically same as indices 1-6 in pandas.
[ 8 10] # 8, 9
[13 14] # 13, 13
[15 19] # 15, 18