2015-09-22 3 views
1

Я ищу быстрый способ вычислить следующее:Преобразования вещественной Numpy массива двоичного массива знакомы

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

Теперь я хочу, чтобы бросить a в массив двоичных значений, таким образом, что он имеет 1 для каждого положительного входа a и 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 

EDIT: временные большие решения из ответов

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

Что вы собираетесь делать с результатом? Я спрашиваю, потому что логический массив, созданный 'a> 0', может работать без преобразования его типа' int' или 'int8'. –

+0

@ WarrenWeckesser Хорошая точка. Я буду вычислять расстояния, такие как hamming, поэтому я проверю, могу ли я быстрее работать с булевыми массивами. – benbo

ответ

3

Вы можете сделать это с использованием маски:

(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 будет достаточно. Это сэкономит вам память и сделает вещи немного быстрее.

3

Вы можете проверить, где a больше 0 и бросьте булев массив целочисленного массива:

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

Это должно быть значительно быстрее, чем метод, предложенный в вопросе (особенно по более крупным массивам), поскольку он избегает циклирования ov er на уровне 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 
Смежные вопросы