Векторный способ заполнения массива NumPy - PullRequest
0 голосов
/ 01 марта 2019

У меня есть какая-то двоичная строка s вроде 001010.Я хочу преобразовать его в массив NumPy a, где a[i] = np.array([[1], [0]]), если s[i] == '0', и в np.array([[0], [1]]) в противном случае.

Итак, я написал такой код:

a = np.empty([len(s), 2, 1])
for i, char in enumerate(s):
    if char == '0':
        a[i] = np.array([[1], [0]])
    elif char == '1':
        a[i] = np.array([[0], [1]])

Можно ли переписать его в векторизованную форму без цикла for более тупо?

Мой ожидаемый результат выглядит следующим образом:

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

       [[1.],
        [0.]],

       [[0.],
        [1.]],

       [[1.],
        [0.]],

       [[0.],
        [1.]],

       [[1.],
        [0.]]])

Ответы [ 2 ]

0 голосов
/ 01 марта 2019

Подход № 1: Вот пример с массивом символов NumPy -

sa = np.frombuffer(s,dtype='S1')
out = np.where(sa[:,None,None]=='0',[[1],[0]],[[0],[1]])

Подход № 2: Еще один однострочный -

((np.frombuffer(s,dtype=np.uint8)[:,None]==[48,49])[...,None]).astype(float)

Подход № 3: Финальный, полностью сфокусированный на производительности -

a = np.zeros([len(s), 2, 1])
idx = np.frombuffer(s,dtype=np.uint8)-48
a[np.arange(len(idx)),idx] = 1

Синхронизация строки 100000 символов -

In [2]: np.random.seed(0)

In [3]: s = ''.join(map(str,np.random.randint(0,2,(100000)).tolist()))

# @yatu's soln
In [4]: %%timeit
     ...: a = np.array(list(s), dtype=int)
     ...: np.where(a==0, np.array([[1], [0]]), np.array([[0], [1]])).T[:,:,None]
10 loops, best of 3: 36.3 ms per loop

# App#1 from this post    
In [5]: %%timeit
     ...: sa = np.frombuffer(s,dtype='S1')
     ...: out = np.where(sa[:,None,None]=='0',[[1],[0]],[[0],[1]])
100 loops, best of 3: 3.56 ms per loop

# App#2 from this post    
In [6]: %timeit ((np.frombuffer(s,dtype=np.uint8)[:,None]==[48,49])[...,None]).astype(float)
1000 loops, best of 3: 1.81 ms per loop

# App#3 from this post    
In [7]: %%timeit
     ...: a = np.zeros([len(s), 2, 1])
     ...: idx = np.frombuffer(s,dtype=np.uint8)-48
     ...: a[np.arange(len(idx)),idx] = 1
1000 loops, best of 3: 1.81 ms per loop
0 голосов
/ 01 марта 2019

Простой способ сделать это - создать list из строки, а затем превратить этот список в np.array целых чисел, указав dtype=int:

s = '001010'

a = np.array(list(s), dtype=int)
# array([0, 0, 1, 0, 1, 0])

И затем использоватьnp.where для выбора из np.array([[1], [0]]) или np.array([[0], [1]]) в соответствии со значениями в a:

np.where(a==0, np.array([[1], [0]]), np.array([[0], [1]])).T[:,:,None]
array([[[1],
        [0]],

       [[1],
        [0]],

       [[0],
        [1]],

       [[1],
        [0]],

       [[0],
        [1]],

       [[1],
        [0]]])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...