按符号将实值numpy数组转换为二进制数组

时间:2015-09-22 20:52:32

标签: python arrays numpy casting

我正在寻找一种快速计算方法:

import numpy as np
a = np.array([-1,1,2,-4,5.5,-0.1,0])

现在我想将a转换为二进制值数组,使得a的每个正条目都为1,否则为0。所以我想要的结果是:

array([ 0.,  1.,  1.,  0.,  1.,  0.,  0.])

实现这一目标的一种方法是

np.array([x if x >=0 else 0 for x in np.sign(a)])
array([ 0.,  1.,  1.,  0.,  1.,  0.,  0.])

但我希望有人可以指出更快的解决方案。

%timeit np.array([x if x >=0 else 0 for x in np.sign(a)])
100000 loops, best of 3: 11.4 us per loop

编辑:为答案提供优秀的解决方案

%timeit (a > 0).astype(int)
100000 loops, best of 3: 3.47 us per loop

2 个答案:

答案 0 :(得分:3)

您可以检查a大于0的位置,并将布尔数组转换为整数数组:

>>> (a > 0).astype(int)
array([0, 1, 1, 0, 1, 0, 0])

这应该明显快于问题中提出的方法(特别是在较大的数组上),因为它避免了在Python级别对数组进行循环。

更快的是简单地将布尔数组视为int8 dtype - 这可以防止需要从布尔数组创建新数组:

>>> (a > 0).view(np.int8)
array([0, 1, 1, 0, 1, 0, 0], dtype=int8)

时序:

>>> b = np.random.rand(1000000)
>>> %timeit np.array([ x if x >=0 else 0 for x in np.sign(b)])
1 loops, best of 3: 420 ms per loop

>>> %timeit (b > 0).astype(int)
100 loops, best of 3: 4.63 ms per loop

>>> %timeit (b > 0).view(np.int8)
1000 loops, best of 3: 1.12 ms per loop

答案 1 :(得分:3)

你可以使用mask:

来做到这一点

(a > 0).astype(int)

我不知道如何正确使用timeit,甚至

import numpy as np
from datetime import datetime
n = 50000000
a = np.random.rand(1, n).ravel()
startTime = datetime.now()
np.array([ x if x >=0 else 0 for x in np.sign(a)])
print datetime.now() - startTime

startTime = datetime.now()
(a > 0).astype(int)
print datetime.now() - startTime
pass

显示 26秒 0.5秒的显着差异。

根据您的评论

P.S。

  

我会计算距离,比如汉明

你真的不需要一个整数数组,而a > 0就足够了。它可以节省你的记忆力,让事情变得更快。