Есть ли возможность конвертировать все столбцы в строках панд / numpy в массивы байтов? - PullRequest
0 голосов
/ 14 февраля 2019

Мне нужно преобразовать каждую строку массива панд / numpy в 1, новый столбец.Мне нужен самый быстрый способ.Я пытался найти метод для извлечения полной строки в виде байтового массива, но не могу найти никакой опции, без итерации всех столбцов, преобразования каждого значения столбца в байты и конкатенации.

В функции row_to_bytes я использую библиотеку hashlib и функцию md5, но мне не нужна криптография.Должен ли я реализовать его в C / C ++ или, может быть, есть какая-то библиотека, которую я могу использовать?

Теперь, это лучший метод, который у меня есть, но он очень медленный (у меня есть таблица с 5 миллионами записей и 40 атрибутами).

hashed = df.apply(lambda row: self.row_to_bytes(row), axis=1)

Спасибо за каждое предложение.


Я создал тестовый код:

import pandas as pd  
import numpy as np  
df = pd.DataFrame([["1",1],["2",2]])  
x = df.values  

def compute(x):  
    dtype = np.dtype('S{:d}'.format(x.shape[1] * x.dtype.itemsize))  
    y = np.frombuffer(x.tobytes(), dtype=dtype)  
    print(y)  
compute(x)  

Когда я несколько раз запускаю код в командной строке, я получаю разныерезультаты:

python test.py
[b'\xb0\x8a\xbb\x8c\xf3\x01\x00\x000\x80og'
 b'p%\xc1\x8c\xf3\x01\x00\x00P\x80og'] 

python test.py     
[b'\xb0\x8aCr,\x02\x00\x000\x80og' b'p%^r,\x02\x00\x00P\x80og'] 

python test.py
[b'\xb0\x8a"\xb7\xc9\x01\x00\x000\x80og' b'p%=\xb7\xc9\x01\x00\x00P\x80og'] 

Что может вызвать еще одну проблему?

Ответы [ 2 ]

0 голосов
/ 15 февраля 2019

Я нашел решение проблемы с преобразованием в байты.

Проблема заключается в автоматическом преобразовании типов столбцов в тип объекта, когда у нас есть столбец со строками.Вместо использования df.values ​​мы можем использовать метод .to_numpy () и явно указывать типы столбцов, например:

dtype = ([('col1', '|S1'), ('col2', 'i4'), ('col3','i4')] )
x = df.to_numpy(dtype = dtype)

Теперь все работает отлично.

Спасибо bnaecker для Вашего решения.

0 голосов
/ 14 февраля 2019

Не нужно зацикливаться.Поскольку вам нужны байты из каждой строки, а массивы являются основными по строкам, байты в том виде, в котором они расположены в памяти, - это именно те байты, которые вам нужны в каждом элементе вашего массива, просто по-разному разбитые на части.Это по определению изменение формы результирующего массива.Вы можете сделать:

>>> x = np.arange(1000 * 2).reshape(100, 2)
>>> dtype = np.dtype('S{:d}'.format(x.shape[1] * x.dtype.itemsize))
>>> y = np.frombuffer(x.tobytes(), dtype=dtype)
>>> print(y[:5])
[b'\x00\x00\x00\x00\x00\x00\x00\x00\x01'
b'\x02\x00\x00\x00\x00\x00\x00\x00\x03'
b'\x04\x00\x00\x00\x00\x00\x00\x00\x05'
b'\x06\x00\x00\x00\x00\x00\x00\x00\x07'
b'\x08\x00\x00\x00\x00\x00\x00\x00\t']

Это заново интерпретирует весь базовый буфер как строки байтов.Каждая такая строка байтов (dtype) имеет длину, равную количеству байтов в каждой строке.

Есть много других способов сделать это на основе цикла, но один из них будет использовать np.fromiter.Мое первое решение на несколько порядков быстрее, чем это, однако, как видно при использовании магической функции IPython * timeit:

In [32]: %timeit np.frombuffer(x.tobytes(), dtype='S16')
2.8 µs ± 318 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

In [33]: %timeit np.fromiter((row.tobytes() for row in x), dtype='S16')
614 µs ± 18.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...