【问题标题】:HDFStore: table.select and RAM usageHDFStore:table.select 和 RAM 使用情况
【发布时间】:2013-03-31 12:32:57
【问题描述】:

我正在尝试从大约 1 GB 的 HDFStore 表中选择随机行。当我请求大约 50 个随机行时,RAM 使用量会激增。

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

在第一种情况下,RAM 使用量适合 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 使用量如此显着增加。

请注意,该表在创建时已被索引,因此 index=range(nrows(table)) 使用以下代码:

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})

感谢您的见解

编辑回答 Zelazny7

这是我用来将 Train.csv 写入 train.h5 的文件。我使用来自 How to trouble-shoot HDFStore Exception: cannot find the correct atom type 的 Zelazny7 代码元素编写了这个代码

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=',')

【问题讨论】:

  • 您使用 HDFStore 的方式似乎与我想使用的方式相似。我没有时间创建处理大量存储和检索的包装器代码。您介意分享您的txtfile2dtypes 代码吗?另外,你的数据有很多字符数据吗?将 csv 文件存储到具有可变字符数据的 HDFStore 时遇到问题。文件大小会爆炸,因为我必须将 min_itemsize 设置为如此大的值。我急切地等待添加truncate 选项。
  • @Zelazny7 我已经用代码更新了线程。实际上,我在与您的数据相同的数据上使用它,即 Kaggle 的推土机。我还没有虚拟化分类变量以使用sklearn
  • 非常感谢!看起来你的文件大小和我的一样膨胀。 ~120mb 文件最终超过 1GB。我想知道您或 Jeff 是否知道使用 put 存储可变长度的 object 列(实际上只是字符串)并将每个文本列保留为自己的 HDFStore 对象是否更好。
  • 我的用例需要更多动手操作。我喜欢在处理建模步骤之前探索角色数据。还有其他方法可以处理名义数据,例如重新编码为目标均值。
  • 只是想给你一个更新。经过大量测试后,我确定 HDFStore 无法正常工作。我正在寻找一个面向列的表结构,不幸的是 HDFStore 不是那样的。因此,我将使用 R 并使用 ff 包。如果您对 R 持开放态度,它也可能对您有用:cran.r-project.org/web/packages/ff/index.html欢呼

标签: python pandas pytables hdfstore


【解决方案1】:

这是一个已知问题,请参阅此处的参考:https://github.com/pydata/pandas/pull/2755

本质上,查询被转换为numexpr 表达式以进行评估。有一个问题 我不能将很多 or 条件传递给 numexpr (它取决于 生成的表达式)。

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

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

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

【讨论】:

  • 好的,谢谢。我错过了问题线程,我应该先搜索 github 论坛。顺便说一句,我刚刚知道您是 hdfstore 开发人员,所以感谢您的出色工作!
  • 这很晦涩,很不幸很容易错过:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多