Рутинно използвам десетки гигабайта данни само в тази мода. Имам таблици на диска, които чета чрез заявки, създавам данни и добавям обратно.
Струва си да прочетете документите и по-късно в тази тема за няколко предложения как да съхранявате данните си.
Подробности, които ще повлияят на това как съхранявате данните си, като:
Дайте колкото можете повече подробности; и мога да ви помогна да разработите структура.
- Размер на данните, брой редове, колони, типове колони; добавяте ли редове или само колони?
- Как ще изглеждат типичните операции. напр. направете заявка за колони, за да изберете куп редове и конкретни колони, след това направете операция (в паметта), създайте нови колони, запазете ги.
(Даването на пример за играчка може да ни позволи да предложим по-конкретни препоръки. ) - След тази обработка какво правите? Стъпка 2 ad hoc ли е или повтаряема?
- Входни плоски файлове:колко, приблизителен общ размер в Gb. Как са организирани тези напр. по записи? Всяко от тях съдържа ли различни полета или има записи на файл с всички полета във всеки файл?
- Избирали ли сте някога подмножества от редове (записи) въз основа на критерии (например избирате редовете с поле A> 5)? и след това направете нещо или просто изберете полета A, B, C с всички записи (и след това направите нещо)?
- Работите ли върху всичките си колони (в групи) или има ли добра част, която може да използвате само за отчети (напр. искате да запазите данните наоколо, но не е необходимо да ги изтегляте яснота на колоната до момента на окончателните резултати)?
Решение
Уверете се, че имате панди поне 0.10.1
инсталиран.
Четете итериращите файлове парче по парче и множество заявки за таблици.
Тъй като pytables е оптимизиран да работи по редове (което е това, към което правите заявка), ние ще създадем таблица за всяка група полета. По този начин е лесно да изберете малка група от полета (която ще работи с голяма таблица, но е по-ефективно да го направите по този начин... Мисля, че може да успея да коригирам това ограничение в бъдеще... това е все пак по-интуитивен):
(По-долу е псевдокод.)
import numpy as np
import pandas as pd
# create a store
store = pd.HDFStore('mystore.h5')
# this is the key to your storage:
# this maps your fields to a specific group, and defines
# what you want to have as data_columns.
# you might want to create a nice class wrapping this
# (as you will want to have this map and its inversion)
group_map = dict(
A = dict(fields = ['field_1','field_2',.....], dc = ['field_1',....,'field_5']),
B = dict(fields = ['field_10',...... ], dc = ['field_10']),
.....
REPORTING_ONLY = dict(fields = ['field_1000','field_1001',...], dc = []),
)
group_map_inverted = dict()
for g, v in group_map.items():
group_map_inverted.update(dict([ (f,g) for f in v['fields'] ]))
Четене на файловете и създаване на хранилището (по същество прави това, което append_to_multiple
прави):
for f in files:
# read in the file, additional options may be necessary here
# the chunksize is not strictly necessary, you may be able to slurp each
# file into memory in which case just eliminate this part of the loop
# (you can also change chunksize if necessary)
for chunk in pd.read_table(f, chunksize=50000):
# we are going to append to each table by group
# we are not going to create indexes at this time
# but we *ARE* going to create (some) data_columns
# figure out the field groupings
for g, v in group_map.items():
# create the frame for this group
frame = chunk.reindex(columns = v['fields'], copy = False)
# append it
store.append(g, frame, index=False, data_columns = v['dc'])
Сега имате всички таблици във файла (всъщност бихте могли да ги съхранявате в отделни файлове, ако желаете, вероятно ще трябва да добавите името на файла към group_map, но вероятно това не е необходимо).
Ето как получавате колони и създавате нови:
frame = store.select(group_that_I_want)
# you can optionally specify:
# columns = a list of the columns IN THAT GROUP (if you wanted to
# select only say 3 out of the 20 columns in this sub-table)
# and a where clause if you want a subset of the rows
# do calculations on this frame
new_frame = cool_function_on_frame(frame)
# to 'add columns', create a new group (you probably want to
# limit the columns in this new_group to be only NEW ones
# (e.g. so you don't overlap from the other tables)
# add this info to the group_map
store.append(new_group, new_frame.reindex(columns = new_columns_created, copy = False), data_columns = new_columns_created)
Когато сте готови за post_processing:
# This may be a bit tricky; and depends what you are actually doing.
# I may need to modify this function to be a bit more general:
report_data = store.select_as_multiple([groups_1,groups_2,.....], where =['field_1>0', 'field_1000=foo'], selector = group_1)
Що се отнася до колоните_данни, всъщност не е необходимо да дефинирате НЯКОЙ колони_данни; те ви позволяват да избирате подизбор на редове въз основа на колоната. напр. нещо като:
store.select(group, where = ['field_1000=foo', 'field_1001>0'])
Те може да са най-интересни за вас на етапа на окончателното генериране на отчет (по същество колона с данни е отделена от други колони, което може да повлияе донякъде на ефективността, ако дефинирате много).
Може също така да:
- създайте функция, която взема списък с полета, търси групите в group_map, след което ги избира и конкатенира резултатите, така че да получите резултантната рамка (това по същество прави select_as_multiple). По този начин структурата ще бъде доста прозрачна за вас.
- индексира определени колони с данни (прави поднабора на редове много по-бърз).
- активиране на компресията.
Кажете ми, когато имате въпроси!