Преобразовать цепочку битов (строка из 1 и 0) в массив NumPy

У меня есть пандас Dataframe, содержащий 1 столбец, который содержит строку битов, например.'100100101', Я хочу преобразовать эту строку в массив NumPy.

Как я могу это сделать?

РЕДАКТИРОВАТЬ:

С помощью

features = df.bit.apply(lambda x: np.array(list(map(int,list(x)))))
#...
model.fit(features, lables)

приводит к ошибке на model.fit:

ValueError: setting an array element with a sequence.

Решение, которое работает для моего случая, я придумал из-за отмеченного ответа:

for bitString in input_table['Bitstring'].values:
    bits = np.array(map(int, list(bitString)))
    featureList.append(bits)
features = np.array(featureList)
#....
model.fit(features, lables)

2 ответа

Решение

Для строки s = "100100101" Вы можете преобразовать его в массив NumPy по крайней мере двумя разными способами.

Первый с помощью Numpy's fromstring метод. Это немного неловко, потому что вы должны указать тип данных и вычесть "базовое" значение элементов.

import numpy as np

s = "100100101"
a = np.fromstring(s,'u1') - ord('0')

print a  # [1 0 0 1 0 0 1 0 1]

куда 'u1' это тип данных и ord('0') используется для вычитания "базового" значения из каждого элемента.

Второй способ заключается в преобразовании каждого строкового элемента в целое число (поскольку строки являются итеративными), а затем передачу этого списка в np.array:

import numpy as np

s = "100100101"
b = np.array(map(int, s))

print b  # [1 0 0 1 0 0 1 0 1]

затем

# To see its a numpy array:
print type(a)  # <type 'numpy.ndarray'>
print a[0]     # 1
print a[1]     # 0
# ...

Обратите внимание, что второй подход масштабируется значительно хуже первого, поскольку длина входной строки s увеличивается. Для небольших строк это близко, но рассмотрим timeit результаты для строк из 90 символов (я только что использовал s * 10):

fromstring: 49.283392424 s
map/array:   2.154540959 s

(Это по умолчанию timeit.repeat аргументы, минимум 3 запуска, каждый из которых вычисляет время для выполнения 1M строк-> преобразований массивов)

Одним из методов pandas было бы вызвать apply для столбца df для выполнения преобразования:

In [84]:

df = pd.DataFrame({'bit':['100100101']})
t = df.bit.apply(lambda x: np.array(list(map(int,list(x)))))
t[0]
Out[84]:
array([1, 0, 0, 1, 0, 0, 1, 0, 1])

Проверьте unpackbits

>>> np.unpackbits(np.array([int('010101',2)], dtype=np.uint8))
array([0, 0, 0, 1, 0, 1, 0, 1], dtype=uint8)

И в целом:

>>> a = np.array([[2], [7], [23]], dtype=np.uint8)
>>> a
array([[ 2],
       [ 7],
       [23]], dtype=uint8)
>>> b = np.unpackbits(a, axis=1)
>>> b
array([[0, 0, 0, 0, 0, 0, 1, 0],
       [0, 0, 0, 0, 0, 1, 1, 1],
       [0, 0, 0, 1, 0, 1, 1, 1]], dtype=uint8)

Если вам нужно больше 8 бит, ознакомьтесь с разделом Как извлечь биты больших числовых типов данных Numpy

Другие вопросы по тегам