我正在编写一个算法来确定" mountains"在密度图上。如果有人感兴趣的话,情节取自Kinect的深度。以下是该算法发现的快速可视化示例:(删除了小山):
我目前的算法:
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)。
答案 0 :(得分:1)
假设pandas
数据框如此:
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
来获取连续的非零范围,以便检查它是否以零为界。一旦获得边界,就可以存储它们的索引对,并在以后过滤数据时使用它们。
以下代码基于the excellent answer here by @behzad.nouri。
import pandas as pd
df = pd.read_csv("data.csv")
# Or you can use df = pd.DataFrame.from_dict({'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}})
# --
# from https://stackoverflow.com/questions/24281936
# credits to @behzad.nouri
df['tag'] = df['Value'] > 0
fst = df.index[df['tag'] & ~ df['tag'].shift(1).fillna(False)]
lst = df.index[df['tag'] & ~ df['tag'].shift(-1).fillna(False)]
pr = [(i, j) for i, j in zip(fst, lst)]
# --
for i, j in pr:
print df.loc[i:j, "Value"]
这给出了结果:
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
数组并从那里进行操作。让我们来看看another excellent answer,@ 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