此代码将选择列表"a"的6个或更多正值
a=np.array([1.01, -1.58, 0.64, 1.38, 0.69, 0.91, 1.34, 1.03, 1.39, 0.94, -1.01,0.16])
b= np.zeros(13)
for i in range(6):
if (a[i] > 0 and a[i+1] > 0 and a[i+2] > 0 and a[i+3] > 0
and a[i+4] > 0 and a[i+5] > 0 and a[i+6] > 0) :
b[i] = a[i]
b[i+1] = a[i+1]
b[i+2] = a[i+2]
b[i+3] = a[i+3]
b[i+4] = a[i+4]
b[i+5] = a[i+5]
b[i+6] = a[i+6]
我想把它缩短,我试过了:
for i in range (6):
if (a[i:i+6]) > 0:
b[i:i+6] = a[i:i+6]
再次访问这个方法-我想添加这个替代方法,其中包括我在以前的回答中提到的优化:
这个版本要长得多,并且需要手工编码每个正数序列的索引跟踪。但它具有主要的性能优势,如下所述。
a = np.array([1.01, -1.58, 0.64, 1.38, 0.69, 0.91, 1.34, 1.03, 1.39, 0.94, -1.01, 0.16,])
b = np.zeros(len(a))
MIN_CONSECUTIVE = 6 # number of consecutive numbers wanted
first, last, c = -1, -1, 0 # index of first & last positive number, count of +ve nums
nums = [] # hold each series of consecutive positive numbers
for i, n in enumerate(a):
if n > 0:
nums.append(n)
first = i if first == -1 else first
last = i
c += 1
else:
if c >= MIN_CONSECUTIVE:
b[first:last+1] = nums
first, last, c = -1, -1, 0 # reset
nums = [] # reset
if i > len(a) - MIN_CONSECUTIVE - 1: # shortcut exit if there aren't
break # enough elems left for consecutive
else: # if the loop completes without `break`
if c >= MIN_CONSECUTIVE: # also check after the loop completes
b[first:last+1] = nums
b # -> array([0. , 0. , 0.64, 1.38, 0.69, 0.91, 1.34, 1.03, 1.39, 0.94, 0. , 0. ])
为什么这样更好:
- 这个访问和访问numpy数组(或python列表(中的每个项目一次。
- 您尝试的方法,在评论和我之前的回答中提供,多次查找数组中重叠的系列元素
- 前一个也多次重新写入
b
,并用相同的值重写
- 这只会在找到并完成每个系列后写入
b
- 我正在使用
enumerate()
跟踪索引,但我不使用索引访问元素。对python列表的索引访问比只遍历列表的元素要慢。numpy数组也是如此 - 对于您给定的列表,此列表的运行时间不到上一个答案的一半:
- 这个:14.6µs±584 ns
- 上一篇:31.9µs±1.13µs
在缩短的版本中,您需要更改的主要内容是if (a[i:i+6]) > 0:
。此外,a
的长度是12,b
的长度是13。编辑1:(根据@Steve下面的评论(此外,索引range
循环也可以从for i in range(6)
推广到for i in range(len(a)-5)
因此:
b = np.zeros(len(a))
# b is
# array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
for i in range(len(a)-5):
if all(a[i:i+6] > 0):
b[i:i+6] = a[i:i+6]
b
# output:
# array([0. , 0. , 0.64, 1.38, 0.69, 0.91, 1.34, 1.03, 1.39, 0.94, 0. , 0. ])
编辑2,根据@hpaulj的评论,由于a
是一个numpy数组,我们不需要迭代切片,因为numpy会将>
运算符应用于数组(切片(的每个元素,并返回一个[
True,
False, ...]
的数组。第一个循环是这样的:
例如a[0:0+6] > 0
返回array([ True, False, True, True, True, True])
。
一次只检查6个元素的一个显著缺点是,如果是一组更长的连续正数,它将在下一个循环中填充,并重写b
中已经存在的相同值。所以不是很优化。最好对索引进行显式检查,直到得到非正(或结束(,并确保您当前处于计数状态>6.