2013-05-15 4 views
9

У меня есть несколько двоичных данных, и мне было интересно, как я могу загрузить это в панды.Чтение двоичных данных в pandas

Могу ли я каким-то образом загрузить его, указав формат, в котором он находится, и что вызывают отдельные столбцы?

Редактировать:
Формат

int, int, int, float, int, int[256] 

каждая разделение запятой представляет собой столбец в данных, то есть последние 256 целых чисел один столбец.

+0

вам нужно поместить его в массив numpy (или python dict/list). это пользовательский формат? или что-то вроде stata? – Jeff

+0

Это нестандартный формат. Некоторые целые числа, некоторые плавающие. – kasperhj

+0

ваш лучший выбор - просто прочитайте с помощью python и создайте массив numpy; если скорость является проблемой, тогда вы можете читать с помощью cython, или если у у вас уже есть читатель в c, тогда вы можете обернуть в cython. – Jeff

ответ

13

Даже если это старый вопрос, мне было интересно то же самое, и я не видел решения, которое мне понравилось.

При чтении двоичных данных с помощью Python я нашел numpy.fromfile или numpy.fromstring намного быстрее, чем с помощью структурного модуля Python. Двоичные данные со смешанными типами можно эффективно считывать в массив numpy, используя вышеописанные методы, если формат данных является постоянным и может быть описан с помощью объекта типа данных numpy().

import numpy as np 
import pandas as pd 

# Create a dtype with the binary data format and the desired column names 
dt = np.dtype([('a', 'i4'), ('b', 'i4'), ('c', 'i4'), ('d', 'f4'), ('e', 'i4'), 
       ('f', 'i4', (256,))]) 
data = np.fromfile(file, dtype=dt) 
df = pd.DataFrame(data.tolist(), columns=data.dtype.names) 
+0

Отличное улучшение. Спасибо, что опубликовали это решение. – kasperhj

+2

Преобразование списка не нужно, используя данные непосредственно в качестве драйвера для фреймворка данных Pandas, ускоряет работу: df = pd.DataFrame (data, columns = data.dtype.names) – fxx

1

Для чего вам нужно начать.

from struct import unpack, calcsize 
from pandas import DataFrame 

entry_format = 'iiifi256i' #int, int, int, float, int, int[256] 
field_names = ['a', 'b', 'c', 'd', 'e', 'f', ] 
entry_size = calcsize(entry_format) 

with open(input_filename, mode='rb') as f: 
    entry_count = os.fstat(f.fileno()).st_size/entry_size 
    for i in range(entry_count): 
     record = f.read(entry_size) 
     entry = unpack(entry_format, record) 
     entry_frame = dict((n[0], n[1]) for n in zip(field_names, entry)) 
     DataFrame(entry_frame) 
+0

С небольшими изменениями в вашем фрагменте (например, 'open (.., mode = 'rb')' и 'os.fstat (input_filename)') Я получаю следующую ошибку: 'DataFrame конструктор неправильно вызван!' – kasperhj

+0

@lejon, Я обновил ответ, чтобы отразить ваши комментарии. –

+1

На самом деле не нужно получать счет здесь .... 'для записи в iter (lambda: f.read (entry_size), ''): # ...' будет делать это –

1

Следующая использует скомпилированную структуру, которая намного быстрее обычной структуры. Альтернативой является использование np.fromstring или np.fromfile, как указано выше.

import struct, ctypes, os 
import numpy as np, pandas as pd 

mystruct = struct.Struct('iiifi256i') 
buff = ctypes.create_string_buffer(mystruct.size) 
with open(input_filename, mode='rb') as f: 
    nrows = os.fstat(f.fileno()).st_size/entry_size 
    dtype = 'i,i,i,d,i,i8' 
    array = np.empty((nrows,), dtype=dtype) 
    for row in xrange(row): 
     buff.raw = f.read(s.size) 
     record = mystruct.unpack_from(buff, 0) 
     #record = np.fromstring(buff, dtype=dtype) 
     array[row] = record 
df = pd.DataFrame(array) 

смотри также http://pymotw.com/2/struct/

7

Недавно я столкнулся с подобной проблемой, с гораздо большей структурой, хотя. Я думаю, что я нашел улучшение ответа на mowen, используя полезный метод DataFrame.from_records. В приведенном выше примере это даст:

import numpy as np 
import pandas as pd 

# Create a dtype with the binary data format and the desired column names 
dt = np.dtype([('a', 'i4'), ('b', 'i4'), ('c', 'i4'), ('d', 'f4'), ('e', 'i4'), ('f', 'i4', (256,))]) 
data = np.fromfile(file, dtype=dt) 
df = pd.DataFrame.from_records(data) 

В моем случае это значительно ускорило процесс. Я предполагаю, что улучшение связано с тем, что вам не нужно создавать промежуточный список Python, а скорее создавать DataFrame из структурированного массива Numpy.