2017-02-17 139 views
1

说我有一个大的2D numpy的阵列,具有多个平等条件语句(称之为一个),其中包含从0整数9.为numpy的阵列

我想写一个返回二进制numpy的阵列功能(称为B),其形状与A相同,具有以下特征。

一个条目是1,如果在相应元素A出现在一个给定的列表大号;否则,条目为零。

下面显示了可能不是最有效的代码。

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 

有没有更快的方法?

谢谢!

回答

2

这里有两个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 
+0

我时序结果提供了不同的叙事。我在anaconda中使用python 3.5和numpy 1.10.4,原始循环大约比使用in1d快3倍。编辑:我现在看到你使用了一个1000x1000的随机矩阵。我将用相同大小的矩阵进行重新测试。 –

+0

@ HAL9001我刚刚测试了python 3,我得到了相当一致的结果。第一个np.in1d选项更快。你正在测试的阵列有多大? – Psidom

+0

Psidom的结果在使用1000x1000时得到确认。 –

2

使用@ Psidom的1000×1000矩阵,我介绍了另外两种方法,并列入@Psidom提供的np.in1d方法。

一个使用迭代求和,另一个使用逐位迭代或。

迭代按位或trial2()证明自己在下面,提供的结果大约比原始快4倍,比numpy的in3d快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  
+0

如果'L'相对于'A'小,'np.in1d'做了'trial2'的迭代版本 - 在'L'上迭代并使用'B | = ...'。 – hpaulj

3

看起来它落在我指出明显:

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