Как быстро преобразовать строку типа '001100' в numpy.array([0,0,1,1,0,0])?
У меня строка состоит из 0 и 1, вроде '00101'
, И я хочу преобразовать его в массив NumPy numpy.array([0,0,1,0,1]
,
я использую for
петля как:
import numpy as np
X = np.zeros((1,5),int)
S = '00101'
for i in xrange(5):
X[0][i] = int(S[i])
Но так как у меня много строк и длина каждой строки равна 1024, этот путь очень медленный. Есть ли лучший способ сделать это?
5 ответов
Карта должна быть немного быстрее, чем список comp:
import numpy as np
arr = np.array(map(int,'00101'))
Некоторые тайминги показывают, что это строка из 1024 символов:
In [12]: timeit np.array([int(c) for c in s])
1000 loops, best of 3: 422 µs per loop
In [13]: timeit np.array(map(int,s))
1000 loops, best of 3: 389 µs per loop
Просто вызов списка в s и использование dtype=int быстрее:
In [20]: timeit np.array(list(s), dtype=int)
1000 loops, best of 3: 329 µs per loop
Использование fromiter и передача dtype=int
опять быстрее:
In [21]: timeit np.fromiter(s,dtype=int)
1000 loops, best of 3: 289 µs per loop
Заимствование из этого ответа с использованием fromstring и uint8 в качестве dtype является самым быстрым:
In [54]: timeit np.fromstring(s, 'int8') - 48
100000 loops, best of 3: 4.54 µs per loop
Даже повторное связывание имени и изменение dtype по-прежнему является самым быстрым:
In [71]: %%timeit
....: arr = np.fromstring(s, 'int8') - 48
....: arr = arr.astype(int)
....:
100000 loops, best of 3: 6.23 µs per loop
Даже значительно быстрее, чем присоединение Ашвини:
In [76]: timeit np.fromstring(' '.join(s), sep=' ', dtype=int)
10000 loops, best of 3: 62.6 µs per loop
Как прокомментировал @Unutbu,np.fromstring(s, 'int8') - 48
не ограничивается единицами и нулями, но будет работать для всех строк, состоящих из цифр ASCII.
Использование numpy.fromstring
:
>>> s = '00101'
>>> np.fromstring(' '.join(s), sep=' ', dtype=int)
array([0, 0, 1, 0, 1])
>>> s = '00101' * 1000
>>> %timeit np.fromiter(s, dtype=int)
100 loops, best of 3: 2.33 ms per loop
>>> %timeit np.fromstring(' '.join(s), sep=' ', dtype=int)
1000 loops, best of 3: 499 µs per loop
Я думаю, что понимание списка будет быстрее, чем ваш обычный метод цикла -
import numpy as np
s = '00101'
np.array([int(c) for c in s])
array([0, 0, 1, 0, 1])
Сравнение времени с вашим методом (с длиной строки 1024) -
In [41]: S = '0' * 512 + '1' * 512
In [43]: %%timeit
....: X = np.zeros((1,len(S)),int)
....: for i in range(len(S)):
....: X[0][i] = int(S[i])
....:
1000 loops, best of 3: 854 µs per loop
In [45]: %%timeit
....: Y = np.array([int(c) for c in S]).reshape((1,len(S)))
....:
1000 loops, best of 3: 339 µs per loop
Я сделал изменение формы, просто чтобы оба массива имели одинаковую форму, но я не думаю, что вам действительно нужно изменение формы, с пониманием списка форма массива, которую вы получите (<length of string> ,)
Как насчет использования метода fromstring?
np.fromstring('1, 2', dtype=int, sep=',')
Подробнее здесь