Python - 在二进制numpy数组中找到1d质心的最佳方法

时间:2016-09-27 07:55:13

标签: python arrays numpy binary boolean

假设我有以下Numpy数组,其中我只有一个1的连续切片:

import numpy as np
x = np.array([0,0,0,0,1,1,1,0,0,0], dtype=1)

我希望找到1元素的1D质心的索引。我可以输入以下内容:

idx = np.where( x )[0]
idx_center_of_mass = int(0.5*(idx.max() + idx.min()))
# this would give 5

(当1 s切片的元素数是偶数时,这会导致粗略的近似。) 有没有更好的方法来做到这一点,比如计算效率更高的oneliner?

2 个答案:

答案 0 :(得分:3)

您不能简单地执行以下操作吗?

center_of_mass = (x*np.arange(len(x))).sum()/x.sum() # 5

%timeit center_of_mass = (x*arange(len(x))).sum()/x.sum()
# 100000 loops, best of 3: 10.4 µs per loop

答案 1 :(得分:2)

作为一种方法,我们可以获得非零指数并得到那些作为质心的平均值,如此 -

np.flatnonzero(x).mean()

这是另一种方法,使用移位数组比较来获得该切片的起始和停止指数,并获得用于确定质心的那些指数的平均值,如下所示 -

np.flatnonzero(x[:-1] != x[1:]).mean()+0.5

运行时测试 -

In [72]: x = np.zeros(10000,dtype=int)

In [73]: x[100:2000] = 1

In [74]: %timeit np.flatnonzero(x).mean()
10000 loops, best of 3: 115 µs per loop

In [75]: %timeit np.flatnonzero(x[:-1] != x[1:]).mean()+0.5
10000 loops, best of 3: 38.7 µs per loop

我们可以使用np.nonzero()[0]替换np.flatnonzeronp.sum取代np.mean -

,从而提高性能
In [107]: %timeit (np.nonzero(x[:-1] != x[1:])[0].sum()+1)/2.0
10000 loops, best of 3: 30.6 µs per loop

或者,对于第二种方法,我们可以存储起始和停止索引,然后简单地添加它们以获得质量中心以获得更有效的方法,因为我们将避免对np.mean的函数调用,如所以 -

start,stop = np.flatnonzero(x[:-1] != x[1:])
out = (stop + start + 1)/2.0

计时 -

In [90]: %timeit start,stop = np.flatnonzero(x[:-1] != x[1:])
10000 loops, best of 3: 21.3 µs per loop

In [91]: %timeit (stop + start + 1)/2.0
100000 loops, best of 3: 4.45 µs per loop

同样,我们可以在这里试验np.nonzero()[0]