Pandas "Group By" запрос на большие данные в HDFStore?
у меня около 7 миллионов строк в HDFStore
с более чем 60 колонок. Данные больше, чем я могу вместить в память. Я ищу, чтобы объединить данные в группы на основе значения столбца "а". Документация для панд разделения/объединения/объединения предполагает, что у меня есть все мои данные в DataFrame
уже, Однако я не могу прочитать весь магазин в память DataFrame
. Каков правильный подход для группировки данных в HDFStore
?
1 ответов
вот полный пример.
import numpy as np
import pandas as pd
import os
fname = 'groupby.h5'
# create a frame
df = pd.DataFrame({'A': ['foo', 'foo', 'foo', 'foo',
'bar', 'bar', 'bar', 'bar',
'foo', 'foo', 'foo'],
'B': ['one', 'one', 'one', 'two',
'one', 'one', 'one', 'two',
'two', 'two', 'one'],
'C': ['dull', 'dull', 'shiny', 'dull',
'dull', 'shiny', 'shiny', 'dull',
'shiny', 'shiny', 'shiny'],
'D': np.random.randn(11),
'E': np.random.randn(11),
'F': np.random.randn(11)})
# create the store and append, using data_columns where I possibily
# could aggregate
with pd.get_store(fname) as store:
store.append('df',df,data_columns=['A','B','C'])
print "store:\n%s" % store
print "\ndf:\n%s" % store['df']
# get the groups
groups = store.select_column('df','A').unique()
print "\ngroups:%s" % groups
# iterate over the groups and apply my operations
l = []
for g in groups:
grp = store.select('df',where = [ 'A=%s' % g ])
# this is a regular frame, aggregate however you would like
l.append(grp[['D','E','F']].sum())
print "\nresult:\n%s" % pd.concat(l, keys = groups)
os.remove(fname)
выход
store:
<class 'pandas.io.pytables.HDFStore'>
File path: groupby.h5
/df frame_table (typ->appendable,nrows->11,ncols->6,indexers->[index],dc->[A,B,C])
df:
A B C D E F
0 foo one dull -0.815212 -1.195488 -1.346980
1 foo one dull -1.111686 -1.814385 -0.974327
2 foo one shiny -1.069152 -1.926265 0.360318
3 foo two dull -0.472180 0.698369 -1.007010
4 bar one dull 1.329867 0.709621 1.877898
5 bar one shiny -0.962906 0.489594 -0.663068
6 bar one shiny -0.657922 -0.377705 0.065790
7 bar two dull -0.172245 1.694245 1.374189
8 foo two shiny -0.780877 -2.334895 -2.747404
9 foo two shiny -0.257413 0.577804 -0.159316
10 foo one shiny 0.737597 1.979373 -0.236070
groups:Index([bar, foo], dtype=object)
result:
bar D -0.463206
E 2.515754
F 2.654810
foo D -3.768923
E -4.015488
F -6.110789
dtype: float64
некоторые предостережения:
1) эта методология имеет смысл, если плотность вашей группы относительно низкая. Порядка сотен или тысяч групп. Если вы получаете больше, чем есть более эффективные (но более сложные методы), и ваша функция, которую вы применяете (в этом случае sum
) становятся более строгими.
по существу, вы бы итератор по всему магазину куски, группировка по мере продвижения, но сохранение групп только наполовину свернутыми (представьте, что вы делаете среднее значение, поэтому вам нужно будет сохранить текущий итог плюс текущий счет, а затем разделить в конце). Поэтому некоторые операции будут немного сложнее, но потенциально могут обрабатывать многие группы (и очень быстро).
2) эффективность этого может быть улучшена путем сохранения координат (например, местоположения групп, но это немного сложнее)
3) мульти-группировать не возможен с эта схема (возможно, но требует подхода больше похожего на 2) выше
4) столбцы, которые вы хотите сгруппировать, должны быть data_column!
5) Вы можете объединить любой другой фильтр, который вы хотите в select btw (который является скрытым способом сделать мульти-группировку btw, вы просто формируете 2 уникальных списка группы и итератора над их продуктом, не очень эффективным, если у вас есть много групп, но может работать)
HTH
позвольте мне знать, если это работает для вы