2016-04-13 3 views
1

Я довольно новичок в пандах, поэтому, пожалуйста, извините, если мои вопросы тривиальны.Сохранение списков переменной длины до HDF5 в pandas

Я хочу сохранить рамку данных pandas в hdf5, которая содержит список списков переменной длины в виде столбца. Моя цель - записать и прочитать в этом фрейме данных позже в chuncks. Это представляется возможным только в том случае, если я храню фрейм данных в формате таблицы. Однако, если я сохранить фрейм данных в виде таблицы я получаю следующее сообщение об ошибке:

TypeError: Cannot serialize the column [pdf] because its data contents are [mixed] object dtype 

В дальнейшем я покажу минимальный пример, чтобы воспроизвести проблему:

import pandas as pd 
import numpy as np 
df = pd.DataFrame() 
df['ID'] = [el for el in np.arange(100)] 
df['pdf'] = [np.arange(i) for i in df['ID']] 
df.to_hdf('test_format_table.h5','df', format='table') 

Если я сохранить кадр данных с format = 'fixed' все будет работать, однако я хочу сохранить в формате таблицы.

Можно ли легко решить эту проблему?

Большое спасибо за помощь.

Markus

ответ

0

Вы приближаетесь эту проблему странным образом. Pandas и HDF5 работают хорошо, когда у вас есть аккуратные данные.

In [32]: df 
Out[32]: 
    ID       pdf 
0 0       [] 
1 1       [0] 
2 2      [0, 1] 
3 3     [0, 1, 2] 
4 4     [0, 1, 2, 3] 
5 5    [0, 1, 2, 3, 4] 
6 6   [0, 1, 2, 3, 4, 5] 
7 7  [0, 1, 2, 3, 4, 5, 6] 
8 8  [0, 1, 2, 3, 4, 5, 6, 7] 
9 9 [0, 1, 2, 3, 4, 5, 6, 7, 8] 

взрываются список для колонн

In [33]: df2 = pd.concat([df.ID, df.pdf.apply(Series)], axis=1) 

In [34]: df2 
Out[34]: 
    ID 0 1 2 3 4 5 6 7 8 
0 0 NaN NaN NaN NaN NaN NaN NaN NaN NaN 
1 1 0.0 NaN NaN NaN NaN NaN NaN NaN NaN 
2 2 0.0 1.0 NaN NaN NaN NaN NaN NaN NaN 
3 3 0.0 1.0 2.0 NaN NaN NaN NaN NaN NaN 
4 4 0.0 1.0 2.0 3.0 NaN NaN NaN NaN NaN 
5 5 0.0 1.0 2.0 3.0 4.0 NaN NaN NaN NaN 
6 6 0.0 1.0 2.0 3.0 4.0 5.0 NaN NaN NaN 
7 7 0.0 1.0 2.0 3.0 4.0 5.0 6.0 NaN NaN 
8 8 0.0 1.0 2.0 3.0 4.0 5.0 6.0 7.0 NaN 
9 9 0.0 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 

переименовать, чтобы сделать понятные имена

In [35]: df2.columns = ['ID'] + [ 'C%s' % c for c in df2.columns[1:] ] 

In [36]: df2 
Out[36]: 
    ID C0 C1 C2 C3 C4 C5 C6 C7 C8 
0 0 NaN NaN NaN NaN NaN NaN NaN NaN NaN 
1 1 0.0 NaN NaN NaN NaN NaN NaN NaN NaN 
2 2 0.0 1.0 NaN NaN NaN NaN NaN NaN NaN 
3 3 0.0 1.0 2.0 NaN NaN NaN NaN NaN NaN 
4 4 0.0 1.0 2.0 3.0 NaN NaN NaN NaN NaN 
5 5 0.0 1.0 2.0 3.0 4.0 NaN NaN NaN NaN 
6 6 0.0 1.0 2.0 3.0 4.0 5.0 NaN NaN NaN 
7 7 0.0 1.0 2.0 3.0 4.0 5.0 6.0 NaN NaN 
8 8 0.0 1.0 2.0 3.0 4.0 5.0 6.0 7.0 NaN 
9 9 0.0 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 

Сделать колонны в ряды

In [47]: df2.stack().reset_index() 
Out[47]: 
    level_0 level_1 0 
0   0  ID 0.0 
1   1  ID 1.0 
2   1  C0 0.0 
3   2  ID 2.0 
4   2  C0 0.0 
..  ...  ... ... 
50  9  C4 4.0 
51  9  C5 5.0 
52  9  C6 6.0 
53  9  C7 7.0 
54  9  C8 8.0 

[55 rows x 3 columns] 

In [48]: df2 = df2.stack().reset_index() 

переименовывать

In [49]: df2.columns = ['A', 'B', 'C'] 

In [50]: df2 
Out[50]: 
    A B C 
0 0 ID 0.0 
1 1 ID 1.0 
2 1 C0 0.0 
3 2 ID 2.0 
4 2 C0 0.0 
.. .. .. ... 
50 9 C4 4.0 
51 9 C5 5.0 
52 9 C6 6.0 
53 9 C7 7.0 
54 9 C8 8.0 

[55 rows x 3 columns] 

Это аккуратные данные, IOW его нормализованный и полезный для работы.

In [51]: df2.to_hdf('test.h5','df',format='table') 
+0

Большое спасибо за ваш ответ. Вы совершенно правы: я решаю эту проблему странным образом. Причина, по которой я делаю это, - это пространство для хранения, поэтому я не делаю никаких дополнений. Я попробовал ваше решение, и он создает файл размером 1,46 Гб, тогда как для моего «решения» требуется только 401,5 МБ. Я использую для этого примера df ['ID'] = [el для el в np.arange (10000)]. Поскольку это слишком большой файл для моих целей, я действительно хочу избежать заполнения. Любая идея, как это можно сделать? – Markus