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) столбцы, которые вы хотите сгруппировать, ДОЛЖНЫ быть столбцами данных!

5) вы можете объединить любой другой фильтр, который вы хотите, в select btw (это хитрый способ сделать несколько групп, кстати, вы просто формируете 2 уникальных списка групп и итератор по их продукту, не очень эффективный, если у вас много из групп, но может работать)

НТН

дайте мне знать, если это работает для вас

Другие вопросы по тегам