我想找到threshold
大于a signal
的第一个样本,而不是查找列表或数组中大于特定threshold
的所有样本/数据点。 signal = [1, 2, 3, 4, 4, 3, 2, 1, 0, 3, 2, 1, 0, 0, 1, 1, 4, 8, 7, 6, 5, 0]
。信号可能会多次超过阈值。例如,如果我有一个示例信号:
threshold = 2
和signal = numpy.array(signal)
is_bigger_than_threshold = signal > threshold
,然后
signal
会在threshold
中为我提供大于first_bigger_than_threshold = list()
first_bigger_than_threshold.append(False)
for i in xrange(1, len(is_bigger_than_threshold)):
if(is_bigger_than_threshold[i] == False):
val = False
elif(is_bigger_than_threshold[i]):
if(is_bigger_than_threshold[i - 1] == False):
val = True
elif(is_bigger_than_threshold[i - 1] == True):
val = False
first_bigger_than_threshold.append(val)
的所有值。
但是,每当信号变得大于阈值时,我想只得到第一个样本。因此,我将浏览整个列表并进行布尔比较,如
[False, False, True, False, False, False, False, False, False, True, False, False, False,
False, False, False, True, False, False, False, False, False]
这给了我正在寻找的结果,即
for i = 2 : numel(is_bigger_than_threshold)
if(is_bigger_than_threshold(i) == 0)
val = 0;
elseif(is_bigger_than_threshold(i))
if(is_bigger_than_threshold(i - 1) == 0)
val = 1;
elseif(is_bigger_than_threshold(i - 1) == 1)
val = 0;
end
end
first_bigger_than_threshold(i) = val;
end % for
在MATLAB中我会做类似的
signal = [round(random.random() * 10) for i in xrange(0, 1000000)]
是否有更有效(更快)的方式来执行此计算?
如果我用Python生成数据,例如
4.45
并计算时间,计算这些值需要signal = round(rand(1, 1000000) * 10);
秒。如果我在MATLAB中生成数据
0.92
执行程序只需{{1}}秒。
为什么MATLAB比执行此任务的速度快5倍?
提前感谢您的评论!
答案 0 :(得分:4)
其他答案会给你第一个真的位置,如果你想要一个标记第一个真的bool数组,你可以更快地完成:
import numpy as np
signal = np.random.rand(1000000)
th = signal > 0.5
th[1:][th[:-1] & th[1:]] = False
答案 1 :(得分:3)
This post解释了为什么你的代码比Matlab慢。
试试此代码
import numpy as np
threshold = 2
signal = np.array([1, 2, 3, 4, 4, 3, 2, 1, 0, 3, 2, 1, 0, 0, 1, 1, 4, 8, 7, 6, 5, 0])
indices_bigger_than_threshold = np.where(signal > threshold)[0] # get item
print indices_bigger_than_threshold
# [ 2 3 4 5 9 16 17 18 19 20]
non_consecutive = np.where(np.diff(indices_bigger_than_threshold) != 1)[0]+1 # +1 for selecting the next
print non_consecutive
# [4 5]
first_bigger_than_threshold1 = np.zeros_like(signal, dtype=np.bool)
first_bigger_than_threshold1[indices_bigger_than_threshold[0]] = True # retain the first
first_bigger_than_threshold1[indices_bigger_than_threshold[non_consecutive]] = True
np.where
返回与条件匹配的索引。
策略是让索引高于threshold
并删除连续的。
答案 2 :(得分:2)
基于这样一种观点,即加快速度的最佳方法是选择最佳算法,您可以使用简单的边缘检测器巧妙地做到这一点:
import numpy
signal = numpy.array([1, 2, 3, 4, 4, 3, 2, 1, 0, 3, 2, 1, 0, 0, 1, 1, 4, 8, 7, 6, 5, 0])
thresholded_data = signal > threshold
threshold_edges = numpy.convolve([1, -1], thresholded_data, mode='same')
thresholded_edge_indices = numpy.where(threshold_edges==1)[0]
print(thresholded_edge_indices)
打印[2 9 16]
,这些索引对应于大于阈值的序列中的第一个条目。这将使Matlab和Python(使用Numpy)的速度更快 - 在我的机器上大约需要12毫秒才能完成4.5秒的操作。
编辑:正如@eickenberg所指出的,卷积可以用numpy.diff(thresholded_data)
替换,这在概念上稍微简单一点,但在这种情况下索引将会超出1,所以请记住将它们添加回来,以及将thresholded_data
转换为thresholded_data.astype(int)
的整数数组。两种方法之间没有明显的速度差异。