我有两个2D numpy数组,例如:
A = numpy.array([[1, 2, 4, 8], [16, 32, 32, 8], [64, 32, 16, 8]])
和
B = numpy.array([[1, 2], [32, 32]])
我希望所有行都A
可以从中找到任何行的所有元素B
。如果一行中有2个相同的元素B
,则from的行也A
必须至少包含2个。以我的示例为例,我想实现以下目标:
A_filtered = [[1, 2, 4, 8], [16, 32, 32, 8]]
我可以控制值的表示形式,因此我选择了二进制表示形式仅占一个位置的数字1
(例如:0b00000001
和0b00000010
等)。这样,通过使用np.logical_or.reduce()
函数,我可以轻松地检查是否所有类型的值都在行中,但是我无法检查连续一行中相同元素的数量是否大于或等于A
。我真的希望我可以避免简单的for
循环和数组的深拷贝,因为性能对我来说是非常重要的方面。
如何以有效的方式在numpy中执行此操作?
更新:
这里的解决方案可能有效,但是我认为性能对我来说是一个很大的问题,它A
可能真的很大(> 300000行),并且B
可能中等(> 30):
[set(row).issuperset(hand) for row in A.tolist() for hand in B.tolist()]
更新2:
该set()
解决方案无法正常工作,因为会set()
丢弃所有重复的值。
希望我能正确回答你的问题。至少它可以解决您在问题中描述的问题。如果输出的顺序应与输入的顺序相同,请更改就地排序。
该代码看起来很丑陋,但是应该表现良好,并且不难理解。
码
import time
import numba as nb
import numpy as np
@nb.njit(fastmath=True,parallel=True)
def filter(A,B):
iFilter=np.zeros(A.shape[0],dtype=nb.bool_)
for i in nb.prange(A.shape[0]):
break_loop=False
for j in range(B.shape[0]):
ind_to_B=0
for k in range(A.shape[1]):
if A[i,k]==B[j,ind_to_B]:
ind_to_B+=1
if ind_to_B==B.shape[1]:
iFilter[i]=True
break_loop=True
break
if break_loop==True:
break
return A[iFilter,:]
衡量绩效
####First call has some compilation overhead####
A=np.random.randint(low=0, high=60, size=300_000*4).reshape(300_000,4)
B=np.random.randint(low=0, high=60, size=30*2).reshape(30,2)
t1=time.time()
#At first sort the arrays
A.sort()
B.sort()
A_filtered=filter(A,B)
print(time.time()-t1)
####Let's measure the second call too####
A=np.random.randint(low=0, high=60, size=300_000*4).reshape(300_000,4)
B=np.random.randint(low=0, high=60, size=30*2).reshape(30,2)
t1=time.time()
#At first sort the arrays
A.sort()
B.sort()
A_filtered=filter(A,B)
print(time.time()-t1)
结果
46ms after the first run on a dual-core Notebook (sorting included)
32ms (sorting excluded)
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句