【问题标题】:Pandas "Group By" Query on Large Data in HDFStore?Pandas 对 HDFStore 中的大数据进行“分组”查询?
【发布时间】:2013-03-25 18:14:34
【问题描述】:

HDFStore 中有大约 700 万行,有 60 多列。数据超出了我的记忆力。我希望根据“A”列的值将数据聚合成组。 pandas splitting/aggregating/combining 的文档假设我的所有数据都在 DataFrame 中,但是我无法将整个存储区读入内存中的 DataFrame。在HDFStore 中分组数据的正确方法是什么?

【问题讨论】:

  • 你看过stackoverflow.com/questions/14262433/…吗? Jeff 的回答是此类工作流程的良好入门
  • 目前正在讨论这作为对 pandas 的未来增强。我当然希望有一天它会被添加,因为我最终可以放弃 SAS:github.com/pydata/pandas/issues/3202
  • 据我了解文档,HDFStore 不支持 DataFrame 上可用的所有操作。您可以尝试使用here 中描述的表查询功能一次手动选择一个组。
  • 你能举一个小例子,说明你将在小组中应用什么样的功能?一个小的示例框架会很有帮助。
  • 还请显示 df.get_dtype_counts() 以及您是否使用 data_columns。谢谢

标签: python pandas pytables


【解决方案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)您可以在选择 btw 中组合您希望的任何其他过滤器(顺便说一句,这是一种狡猾的多分组方式,您只需在它们的乘积上形成 2 个唯一的组和迭代器列表,如果你有很多组,但可以工作)

HTH

让我知道这是否适合你

【讨论】:

  • 谢谢杰夫。如果可以的话,我会给你加分,以便将这个示例(以及返回 SO!的链接)添加到 git 票证中。
  • 您还制作了食谱(但尚未更新此问题),请参阅:pandas.pydata.org/pandas-docs/dev/cookbook.html#hdfstore
  • 在更高版本的 pandas 中,groups = store.unique('df','A') 行应改为 groups = store.select_column('df', 'A').unique()
  • 但是store.select_column('df','A').unique() 会触发全读,如果df['A'] 太大而无法放入内存怎么办?
猜你喜欢
  • 1970-01-01
  • 2014-04-13
  • 1970-01-01
  • 2014-05-11
  • 2021-06-03
  • 1970-01-01
  • 2018-03-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多