获取 ndArray / list 的所有其他索引



给定一个值数组和一个有效的索引数组,我想获取所有其他索引。

寻找一种pythonic方法来做到这一点,但这里有一个解决方案的例子,并澄清了我想要完成什么:

A = np.array(['a', 'b', 'c', 'd', 'e', 'f', 'g'])  # Array of values. Shape: (7,)
B = np.array([0,3,5])  # Array of indices.
# Looking for a more elegant way to do this following line
C = np.array([i for i in range(len(A)) if i not in B])  # Array indices not in B
# Expected Output: C = [1, 2, 4, 6]

编辑:对解决方案进行基准测试

A = np.ones(10000)  
B = np.random.random_integers(low=0, high=len(A) - 1, size=8000)  
t1 = time()  
mask = np.ones(len(A), dtype=bool)  
mask[B] = False  
C = np.arange(len(A))[mask]  
t1 = time() - t1  
t2 = time()  
C = np.delete(np.arange(A.size), B)  
t2 = time() - t2  
t3 = time()  
C = np.array([i for i in range(len(A)) if i not in B])  
t3 = time() - t3  
t4 = time()  
C = set(np.arange(len(A))).difference(B)  
t4 = time() - t4  
print("T1: %.5f" % np.round(t1, 5))    
print("T2: %.5f" % np.round(t2, 5))  
print("T3: %.5f" % np.round(t3, 5))  
print("T4: %.5f" % np.round(t4, 5))  

结果(当B中的指数数量发生变化时,值会发生变化,但最快的指数始终保持T1

T1: 0.00011 <<<多次运行上述脚本,这始终是最快的。第二种方法总是有点落后。>

T2: 0.00017 T3: 0.05746 <<列表理解花费的时间最多。即使在删除 np.array 之后。
T4: 0.00158

  • 结论:
    我将使用上面的第二种方法(T2),因为它是单行并且(几乎)与最快的方法花费相同的时间。
您可以使用

np.delete从可以使用np.arange创建的其他索引列表中删除B项:

inds = np.delete(np.arange(A.size), B)

演示:

In [53]: A = np.array(['a', 'b', 'c', 'd', 'e', 'f', 'g'])
    ...: B = np.array([0,3,5])
In [54]: inds = np.delete(np.arange(A.size), B)
In [55]: inds
Out[55]: array([1, 2, 4, 6])

我不确定这是Pythonic,但它更像Numpythonic(如果这是一件事的话)。首先,对数组的查找是 O(N)。其次,下降到Python迭代(在你的列表理解中)首先破坏了使用numpy数组的目的。

A = np.array([1,2,3,4,5,6,7]) 
B = np.array([0,3,5])
mask = np.ones(len(A), dtype=bool)
mask[B] = False
not_in_b = np.arange(len(A))[mask]

编辑

一些基准。

In [9]: a = np.ones(1000000)
In [10]: b = np.random.choice(1000000, size=10000, replace=False)
In [11]: def test1(a, b):
    ...:     mask = np.ones(len(a), dtype=bool)
    ...:     mask[b] = False
    ...:     return np.arange(len(a))[mask]
    ...: 
    ...: 
In [12]: %timeit test1(a, b)
4.72 ms ± 15 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [13]: %timeit np.delete(np.arange(a.size), b)
4.72 ms ± 21.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

令人惊讶的是,@Kasramvd的解决方案并不比我的快,尽管它相当干净。鉴于此结果,如果np.delete实际上是我实现的相同逻辑的薄包装器,我不会感到惊讶。因此,我认为没有理由更喜欢我的解决方案而不是@Kasramvd的解决方案。

相关内容

最新更新