从pandas.HDFStore表中选择列

时间:2012-12-18 04:08:09

标签: python pandas hdfs

如何从pandas HDFStore中检索特定列?我经常处理非常大的数据集,这些数据集太大而无法在内存中操作。我想迭代地读取一个csv文件,将每个块附加到HDFStore对象中,然后处理数据的子集。我已经阅读了一个简单的csv文件,并使用以下代码将其加载到HDFStore中:

tmp = pd.HDFStore('test.h5')
chunker = pd.read_csv('cars.csv', iterator=True, chunksize=10, names=['make','model','drop'])
tmp.append('df', pd.concat([chunk for chunk in chunker], ignore_index=True))

输出:

In [97]: tmp
Out[97]:
<class 'pandas.io.pytables.HDFStore'>
File path: test.h5
/df     frame_table (typ->appendable,nrows->1930,indexers->[index])

我的问题是如何从tmp['df']访问特定列?该文档提到了select()方法和一些Term个对象。提供的示例适用于小组数据;然而,我太过新手,无法将其扩展到更简单的数据框案例。我的猜测是我必须以某种方式创建列的索引。谢谢!

3 个答案:

答案 0 :(得分:12)

您可以使用列索引存储数据框,如下所示:

import pandas as pd
import numpy as np
from pandas.io.pytables import Term

index = pd.date_range('1/1/2000', periods=8)
df = pd.DataFrame( np.random.randn(8,3), index=index, columns=list('ABC'))  

store = pd.HDFStore('mydata.h5')
store.append('df_cols', df, axes='columns')

然后按照您的意愿选择:

In [8]: store.select('df_cols', [Term('columns', '=', 'A')])
Out[8]: 
2000-01-01    0.347644
2000-01-02    0.477167
2000-01-03    1.419741
2000-01-04    0.641400
2000-01-05   -1.313405
2000-01-06   -0.137357
2000-01-07   -1.208429
2000-01-08   -0.539854

其中:

In [9]: df
Out[9]: 
                   A         B         C
2000-01-01  0.347644  0.895084 -1.457772
2000-01-02  0.477167  0.464013 -1.974695
2000-01-03  1.419741  0.470735 -0.309796
2000-01-04  0.641400  0.838864 -0.112582
2000-01-05 -1.313405 -0.678250 -0.306318
2000-01-06 -0.137357 -0.723145  0.982987
2000-01-07 -1.208429 -0.672240  1.331291
2000-01-08 -0.539854 -0.184864 -1.056217

对我而言,这不是一个理想的解决方案,因为我们只能通过一件事索引DataFrame!令人担忧the docs似乎建议您只能将DataFrame索引一件事,至少使用axes

  

将axes关键字传递给维度列表(当前必须比对象的总维度少1个)。

我可能读错了,在这种情况下希望有人可以证明我错了!

注意:我发现通过两件事(索引和列)索引DataFrame的一种方法是将其转换为Panel,然后可以使用两个索引进行检索。但是,每次检索项目时,我们都必须转换为选定的子面板到DataFrame ...再次,不理想。

答案 1 :(得分:12)

HDFStore记录表的方式,列按类型存储为单个numpy数组。你总是回到所有列,你可以过滤它们,所以你会根据你的要求返回。在0.10.0中,您可以传递涉及列的术语。

store.select('df', [ Term('index', '>', Timestamp('20010105')), 
                     Term('columns', '=', ['A','B']) ])

或者你可以在之后重新索引

df = store.select('df', [ Term('index', '>', Timestamp('20010105') ])
df.reindex(columns = ['A','B'])

axes实际上不是解决方案(实际创建的实际上是存储转置帧)。此参数允许您重新排序轴的存储,以便以不同方式进行数据对齐。对于数据帧而言,这并不意味着什么;对于3d或4d结构,磁盘数据对齐对于真正快速的查询至关重要。

0.10.1将允许更优雅的解决方案,即数据列,也就是说,您可以选择某些列表示为表存储中的自己的列,因此您实际上可以只选择它们。这是一种即将到来的品味。

 store.append('df', columns = ['A','B','C'])
 store.select('df', [ 'A > 0', Term('index', '>', Timestamp(2000105)) ])

另一种方法是在文件的不同节点中存储单独的表,然后您只能选择所需的内容。

一般来说,我再推荐一个很宽的桌子。 hayden提供了Panel解决方案,这对您来说可能是一个好处,因为实际的数据安排应该反映您想要查询数据的方式。

答案 2 :(得分:0)

从现在开始,U可以使用查询表达式代替Term的构造。 例如:store.select('df', "index > Timestamp('20000105')")