2013-11-27 81 views
1

我想了解理想的方式来组织熊猫内的数据以实现最佳的聚合性能。我正在处理的数据是yyyy-mm.csv格式,我只是在read_csv中,然后是to_hdf。它通常看起来有点像这样:熊猫和HDF5聚合性能

的ObjectID时间戳至尊ParamB - > ParamZ
1 2013-01-01 00:00:00 1 9
2 2013-01-01 00:00:00 3 2
1 2013-01-01 00:10:00 8 11
2 2013-01-01 00:10:00 6 14

有大约50的对象ID和读数为10分钟每批整个月。我想要达到的最终结果是在5年内按月分组的单个参数(例如,平均值)的汇总数据。

到目前为止我发现的是,单列的HDFStore.select并不比一次将所有这些参数引入单个数据帧更快。因此感觉非常浪费,表现并不好。如果不知道这是为什么,我不能确定最佳的前进方式。看起来,如果将数据转置为使得yyyy-mm沿着x轴并且dd hh:mm:ss沿y轴向下,并且每个参数有一个这样的数据帧,则性能将会大大提高可以在一击中带来更多数据。从磁盘读入数据后,groupby的速度非常快。然而,我完全不相信这是它应该如何使用。任何人都可以建议组织和存储数据的最佳方式吗?

感谢

+0

请显示一个示例框架,其中包含要使用可运行代码进行聚合的示例框架(当然小尺寸)。 – Jeff

+0

也显示你现在正在做的事情的代码 – Jeff

回答

1

PLS审查面向行的格式HDFStore文档here和cookboo recipies here

PyTables存储数据,所以您有义务通常有较长的和不那么宽表。但是,如果您倾向于查询并需要/需要整行,那么宽度不会造成问题。另一方面,如果您通常在一小列的子集之后,您将希望将表分成多个(可能具有相同的索引方案),因此您可以使用'master'表来运行查询,然后根据需要选择“列”(其他表)。例如,您可以通过append_to_multiple/select_from_multiple方法完成此操作。在极端情况下,您可以将单个列存储在单独的组中,并使您成为一个列式表。然而,如果你倾向于选择很多列,这将大大减慢。

此外,您总是希望将可查询列设置为indexesdata_columns,因为这些列首先允许查询并进行索引。

所以它归结为选择大量列与单列选择的查询比例。

例如

In [5]: df = DataFrame(np.random.randn(16,2), 
         columns=['A','B'], 
         index=MultiIndex.from_tuples(
          [ (i,j) for i in range(4) for j in date_range(
            '20130101 00:00:00',periods=4,freq='10T') ], 
          names=['id','date'])) 

In [6]: df 
Out[6]: 
           A   B 
id date         
0 2013-01-01 00:00:00 -0.247945 0.954260 
    2013-01-01 00:10:00 1.035678 -0.657710 
    2013-01-01 00:20:00 -2.399376 -0.188057 
    2013-01-01 00:30:00 -1.043764 0.510098 
1 2013-01-01 00:00:00 -0.009998 0.239947 
    2013-01-01 00:10:00 2.038563 0.640080 
    2013-01-01 00:20:00 1.123922 -0.944170 
    2013-01-01 00:30:00 -1.757766 -1.398392 
2 2013-01-01 00:00:00 -1.053324 -1.015211 
    2013-01-01 00:10:00 0.062408 -1.476484 
    2013-01-01 00:20:00 -1.202875 -0.747429 
    2013-01-01 00:30:00 -0.798126 -0.485392 
3 2013-01-01 00:00:00 0.496098 0.700073 
    2013-01-01 00:10:00 -0.042914 1.099115 
    2013-01-01 00:20:00 -1.762597 -0.239100 
    2013-01-01 00:30:00 -0.344125 -1.607524 

[16 rows x 2 columns] 

在0.12,使用table=True而非format

In [7]: df.to_hdf('test.h5','df',mode='w',format='table') 

In [8]: store = pd.HDFStore('test.h5') 

In [9]: store 
Out[9]: 
<class 'pandas.io.pytables.HDFStore'> 
File path: test.h5 
/df   frame_table (typ->appendable_multi,nrows->16,ncols->4,indexers->[index],dc->[date,id]) 

In [10]: store.select('df',where='id=0') 
Out[10]: 
           A   B 
id date         
0 2013-01-01 00:00:00 -0.247945 0.954260 
    2013-01-01 00:10:00 1.035678 -0.657710 
    2013-01-01 00:20:00 -2.399376 -0.188057 
    2013-01-01 00:30:00 -1.043764 0.510098 

[4 rows x 2 columns] 

这是0.13语法,这是在0比较麻烦一些。12

In [18]: store.select('df',where='date>"20130101 00:10:00" & date<"20130101 00:30:00"') 
Out[18]: 
           A   B 
id date         
0 2013-01-01 00:20:00 -2.399376 -0.188057 
1 2013-01-01 00:20:00 1.123922 -0.944170 
2 2013-01-01 00:20:00 -1.202875 -0.747429 
3 2013-01-01 00:20:00 -1.762597 -0.239100 

[4 rows x 2 columns] 

In [19]: store.close() 

因此,例如,做对ID的GROUPBY,您可以选择所有的唯一ID(使用select_column方法。在这些然后重复,做一个查询,并将结果进行的功能。这会相当快,这些都是索引列事情是这样的:

In [24]: ids = store.select_column('df','id').unique() 

In [25]: ids 
Out[25]: array([0, 1, 2, 3]) 

In [27]: pd.concat([ store.select('df',where='id={0}'.format(i)).sum() for i in ids ],axis=1) 
Out[27]: 
      0   1   2   3 
A -2.655407 1.394721 -2.991917 -1.653539 
B 0.618590 -1.462535 -3.724516 -0.047436 

[2 rows x 4 columns] 

多GROUPBY仅仅是一个组合查询,如id=1 & date>="20130101 00:10:00' & date<='20130101 00:30:00'

您可能会发现这个例子启发以及here