2013-04-09 73 views
6

我想从大约1 GB的HDFStore表中选择随机行。当我询问大约50个随机行时,RAM使用情况爆发。HDFStore:table.select和RAM使用

我正在使用熊猫0-11-dev, python 2.7, linux64

在第一种情况下的内存使用适合的chunk

with pd.get_store("train.h5",'r') as train: 
for chunk in train.select('train',chunksize=50): 
    pass 

大小在第二种情况下,它似乎是整个表被加载到RAM

r=random.choice(400000,size=40,replace=False) 
train.select('train',pd.Term("index",r)) 

在后一种情况下, RAM使用量适合等效chunk尺寸

r=random.choice(400000,size=30,replace=False)  
train.select('train',pd.Term("index",r)) 

我很困惑,为什么从30行到40行随机行会导致RAM使用量急剧增加。

注创建诸如当表已被索引,使用下面的代码索引=范围(NROWS(表)):

def txtfile2hdfstore(infile, storefile, table_name, sep="\t", header=0, chunksize=50000): 
    max_len, dtypes0 = txtfile2dtypes(infile, sep, header, chunksize) 

    with pd.get_store(storefile,'w') as store: 
     for i, chunk in enumerate(pd.read_table(infile,header=header,sep=sep,chunksize=chunksize, dtype=dict(dtypes0))): 
      chunk.index= range(chunksize*(i), chunksize*(i+1))[:chunk.shape[0]] 
      store.append(table_name,chunk, min_itemsize={'values':max_len}) 

感谢洞察

编辑以ANSWER Zelazny7

这是我用来写Train.csv到train.h5的文件。我写的Zelazny7代码此使用的元素从How to trouble-shoot HDFStore Exception: cannot find the correct atom type

import pandas as pd 
import numpy as np 
from sklearn.feature_extraction import DictVectorizer 


def object_max_len(x): 
    if x.dtype != 'object': 
     return 
    else: 
     return len(max(x.fillna(''), key=lambda x: len(str(x)))) 

def txtfile2dtypes(infile, sep="\t", header=0, chunksize=50000): 
    max_len = pd.read_table(infile,header=header, sep=sep,nrows=5).apply(object_max_len).max() 
    dtypes0 = pd.read_table(infile,header=header, sep=sep,nrows=5).dtypes 

    for chunk in pd.read_table(infile,header=header, sep=sep, chunksize=chunksize): 
     max_len = max((pd.DataFrame(chunk.apply(object_max_len)).max(),max_len)) 
     for i,k in enumerate(zip(dtypes0[:], chunk.dtypes)): 
      if (k[0] != k[1]) and (k[1] == 'object'): 
       dtypes0[i] = k[1] 
    #as of pandas-0.11 nan requires a float64 dtype 
    dtypes0.values[dtypes0 == np.int64] = np.dtype('float64') 
    return max_len, dtypes0 


def txtfile2hdfstore(infile, storefile, table_name, sep="\t", header=0, chunksize=50000): 
    max_len, dtypes0 = txtfile2dtypes(infile, sep, header, chunksize) 

    with pd.get_store(storefile,'w') as store: 
     for i, chunk in enumerate(pd.read_table(infile,header=header,sep=sep,chunksize=chunksize, dtype=dict(dtypes0))): 
      chunk.index= range(chunksize*(i), chunksize*(i+1))[:chunk.shape[0]] 
      store.append(table_name,chunk, min_itemsize={'values':max_len}) 

应用为

txtfile2hdfstore('Train.csv','train.h5','train',sep=',') 
+0

您似乎正在使用HDFStore以类似的方式,我想如何使用它。我没有时间去创建处理大量存储和检索的包装器代码。你介意分享你的'txtfile2dtypes'代码吗?另外,你的数据是否有很多字符数据?将csv文件存储到带有可变字符数据的HDFStore时遇到问题。由于我必须将'min_itemsize'设置为如此大的值,因此文件大小会变大。我急切地等待添加一个'truncate'选项。 – Zelazny7 2013-04-09 13:54:09

+1

@ Zelazny7我用代码更新了线程。事实上,我正在使用它与您的相同的数据,Kaggle的推土机的东西。我还没有将分类变量虚拟成“sklearn”。 – user17375 2013-04-09 14:44:40

+1

非常感谢!它看起来像你的文件大小与我的相同。 〜120MB文件最终超过1GB。我想知道你或Jeff是否会知道使用'put'来存储可变长度的'object'列(实际上只是字符串)是更好的,并将每个文本列保留为它自己的HDFStore对象。 – Zelazny7 2013-04-09 14:53:09

回答

6

这是一个已知的问题,在这里看到的参考:https://github.com/pydata/pandas/pull/2755

本质上查询变成numexpr表达评估。有一个问题 ,在这里我不能将很多or条件传递给numexpr(它取决于生成的表达式的 的总长度)。

所以我只是限制了我们传递给numexpr的表达式。如果它超过了一定数量的or条件,那么查询将作为过滤器完成,而不是内核选择。基本上这意味着表格被读取并重新编制索引。

这是在我的增强列表中:https://github.com/pydata/pandas/issues/2391(17)。

作为一种解决方法,只需将您的查询拆分为多个并对结果进行连接即可。应该更快,并使用恒定数量的内存

+1

好的,谢谢。我错过了这个问题,我应该先搜索github论坛。顺便说一下,我只是意识到你是hdfstore开发人员,所以感谢你的伟大工作! – user17375 2013-04-09 12:59:26

+0

这是相当隐晦和不幸的容易错过:) – Jeff 2013-04-09 13:20:02