NumPy数组有多个相等条件

bejyjqdl  于 2023-05-13  发布在  其他
关注(0)|答案(3)|浏览(143)

假设我有一个大型2D numpy数组(称之为A),其中包含从0到9的整数。
我正在尝试编写一个函数,该函数返回一个与A形状相同的二进制NumPy数组(称之为B),该数组具有以下特性。
如果A中的对应元素出现在给定列表L中,则B中的条目为1;否则,条目为零。
下面显示了可能不是最有效的代码。

A = np.random.randint(0, 10, (5, 5))
L = [3,4,5]

B = np.zeros(A.shape)
for e in L:
    B[A==e] = 1

有更快的路吗?

6vl6ewon

6vl6ewon1#

看来我福尔斯指出一个显而易见的事实

def AinL(A, L):
    B = np.zeros((10,), int)
    B[L] = 1
    return B[A]

基准:

10x10 #L=3
orig     0.6665631101932377
HAL      0.4370500799268484
Psidom   1.13961720908992
PP       0.23527960386127234

 100x100 #L=3
orig     0.3015591569710523
HAL      0.29902734607458115
Psidom   0.4470538650639355
PP       0.18963343487121165

 1000x1000 #L=4
orig     0.5516874771565199
HAL      0.5967503408901393
Psidom   0.6331975681241602
PP       0.23225238709710538

 10000x1000 #L=2
orig     0.8539429588709027
HAL      0.9840140701271594
Psidom   1.0392512339167297
PP       0.7203555379528552
ttygqcqt

ttygqcqt2#

这里有两个numpy选项,其中np.in1d是基础python中in的矢量化版本。当数组很大时,第一个选项显示速度有所提高:

  • 选项一(快速)*:
np.in1d(A, L).reshape(A.shape).astype(int)
  • 选项二(慢一)*:
np.apply_along_axis(np.in1d, 0, A, L).astype(int)
  • 时间 *:
A = np.random.randint(0, 10, (1000, 1000))
L = [3,4,5]
​
def loop():
    B = np.zeros(A.shape)
    for e in L:
        B[A==e] = 1
    return B

%timeit np.in1d(A, L).reshape(A.shape).astype(int)
# 100 loops, best of 3: 6.4 ms per loop

%timeit loop()
# 100 loops, best of 3: 16.8 ms per loop

%timeit np.apply_along_axis(np.in1d, 1, A, L).astype(int)
# 10 loops, best of 3: 21.5 ms per loop

%timeit np.apply_along_axis(np.in1d, 0, A, L).astype(int)
# 10 loops, best of 3: 35.1 ms per loop
  • 结果检查 *:
B1 = loop()
B2 = np.apply_along_axis(np.in1d, 0, A, L).astype(int)
B3 = np.apply_along_axis(np.in1d, 1, A, L).astype(int)
B4 = np.in1d(A, arrL).reshape(A.shape).astype(int)

(B1 == B2).all()
# True

(B1 == B3).all()
# True

(B1 == B4).all()
# True
2jcobegt

2jcobegt3#

使用@Psidom的1000 x1000矩阵,我引入了另外两个方法,包括@Psidom提供的np.in1d方法。
一个使用迭代求和,另一个使用迭代逐位或。
迭代的按位or,trial2(),在下面证明了自己,提供的结果比原始的快4倍,比3d中的numpy快2倍,但是请注意,它提供了一个布尔类型的矩阵结果。
当按位方法被修改为返回整数结果trial2_int()时,其速度基本上相当于numpy的in1d

A = np.random.randint(0,10,(1000,1000))
L = [3,4,5]
def original():
  B = np.zeros(A.shape)
  for e in L:
      B[A==e] = 1
  return B

def trial1():
  B = np.empty(A.shape)
  for e in L:
    B += A == e
  return B

def trial2():
  B = A==L[0]
  for e in L[1:]:
    B |= A == e
  return B

def trial2_int():
  B = trial2()
  return B.astype(int)

def trial_Psidom():
  B = np.in1d(A,L).reshape(A.shape).astype(int)
  return B

结果:

%timeit original()
# 100 loops, best of 3: 10.5 ms per loop
%timeit trial1()
# 100 loops, best of 3: 9.43 ms per loop
%timeit trial2()
# 100 loops, best of 3: 2.37 ms per loop
%timeit trial2_int()
# 100 loops, best of 3: 5.31 ms per loop
%timeit trial_Psidom()
# 100 loops, best of 3: 5.37 ms per loop

相关问题