首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >当我用"pandas.read_hdf()“读取巨大的pandas.read_hdf文件时,即使我通过指定块大小来读取块,为什么仍然会得到MemoryError呢?

当我用"pandas.read_hdf()“读取巨大的pandas.read_hdf文件时,即使我通过指定块大小来读取块,为什么仍然会得到MemoryError呢?
EN

Stack Overflow用户
提问于 2015-06-02 03:54:52
回答 1查看 19.7K关注 0票数 15

问题描述:

我用巨蟒熊猫来读取一些大型的CSV文件,并将其存储在HDF5文件中,结果HDF5文件大约是10 is。这个问题在阅读时会发生。即使我试着把它读回来,我还是得到了MemoryError.

下面是我如何创建HDF5文件:

代码语言:javascript
运行
复制
import glob, os
import pandas as pd

hdf = pd.HDFStore('raw_sample_storage2.h5')

os.chdir("C:/RawDataCollection/raw_samples/PLB_Gate")
for filename in glob.glob("RD_*.txt"):
    raw_df = pd.read_csv(filename,
                         sep=' ',
                         header=None, 
                         names=['time', 'GW_time', 'node_id', 'X', 'Y', 'Z', 'status', 'seq', 'rssi', 'lqi'], 
                         dtype={'GW_time': uint32, 'node_id': uint8, 'X': uint16, 'Y': uint16, 'Z':uint16, 'status': uint8, 'seq': uint8, 'rssi': int8, 'lqi': uint8},
                         parse_dates=['time'], 
                         date_parser=dateparse, 
                         chunksize=50000, 
                         skip_blank_lines=True)
    for chunk in raw_df:
        hdf.append('raw_sample_all', chunk, format='table', data_columns = True, index = True, compression='blosc', complevel=9)

下面是我试着把它读回来的方法:

代码语言:javascript
运行
复制
for df in pd.read_hdf('raw_sample_storage2.h5','raw_sample_all', chunksize=300000):
    print(df.head(1))

下面是我收到的错误消息:

代码语言:javascript
运行
复制
---------------------------------------------------------------------------
MemoryError                               Traceback (most recent call last)
<ipython-input-7-ef278566a16b> in <module>()
----> 1 for df in pd.read_hdf('raw_sample_storage2.h5','raw_sample_all', chunksize=300000):
      2     print(df.head(1))

C:\Anaconda\lib\site-packages\pandas\io\pytables.pyc in read_hdf(path_or_buf, key, **kwargs)
    321         store = HDFStore(path_or_buf, **kwargs)
    322         try:
--> 323             return f(store, True)
    324         except:
    325 

C:\Anaconda\lib\site-packages\pandas\io\pytables.pyc in <lambda>(store, auto_close)
    303 
    304     f = lambda store, auto_close: store.select(
--> 305         key, auto_close=auto_close, **kwargs)
    306 
    307     if isinstance(path_or_buf, string_types):

C:\Anaconda\lib\site-packages\pandas\io\pytables.pyc in select(self, key, where, start, stop, columns, iterator, chunksize, auto_close, **kwargs)
    663                            auto_close=auto_close)
    664 
--> 665         return it.get_result()
    666 
    667     def select_as_coordinates(

C:\Anaconda\lib\site-packages\pandas\io\pytables.pyc in get_result(self, coordinates)
   1346                     "can only use an iterator or chunksize on a table")
   1347 
-> 1348             self.coordinates = self.s.read_coordinates(where=self.where)
   1349 
   1350             return self

C:\Anaconda\lib\site-packages\pandas\io\pytables.pyc in read_coordinates(self, where, start, stop, **kwargs)
   3545         self.selection = Selection(
   3546             self, where=where, start=start, stop=stop, **kwargs)
-> 3547         coords = self.selection.select_coords()
   3548         if self.selection.filter is not None:
   3549             for field, op, filt in self.selection.filter.format():

C:\Anaconda\lib\site-packages\pandas\io\pytables.pyc in select_coords(self)
   4507             return self.coordinates
   4508 
-> 4509         return np.arange(start, stop)
   4510 
   4511 # utilities ###

MemoryError: 

我的python环境:

代码语言:javascript
运行
复制
INSTALLED VERSIONS
------------------
commit: None
python: 2.7.3.final.0
python-bits: 32
OS: Windows
OS-release: 7
machine: x86
processor: x86 Family 6 Model 42 Stepping 7, GenuineIntel
byteorder: little
LC_ALL: None
LANG: None

pandas: 0.15.2
nose: 1.3.4
Cython: 0.22
numpy: 1.9.2
scipy: 0.15.1
statsmodels: 0.6.1
IPython: 3.0.0
sphinx: 1.2.3
patsy: 0.3.0
dateutil: 2.4.1
pytz: 2015.2
bottleneck: None
tables: 3.1.1
numexpr: 2.3.1
matplotlib: 1.4.3
openpyxl: 1.8.5
xlrd: 0.9.3
xlwt: 0.7.5
xlsxwriter: 0.6.7
lxml: 3.4.2
bs4: 4.3.2
html5lib: None
httplib2: None
apiclient: None
rpy2: None
sqlalchemy: 0.9.9
pymysql: None
psycopg2: None

编辑1:

在执行read_hdf()之后大约花了半个小时才发生MemoryError,同时我检查了taskmgr,几乎没有什么CPU活动,使用的总内存从未超过2.2g。在执行代码之前大约是2.1GB。因此,加载到内存中的熊猫read_hdf()小于100 MB (我有4G内存,我的32位Windows系统只能使用2.7G,其余的只能用于内存磁盘)

这里是hdf文件信息:

代码语言:javascript
运行
复制
In [2]:
hdf = pd.HDFStore('raw_sample_storage2.h5')
hdf

Out[2]:
<class 'pandas.io.pytables.HDFStore'>
File path: C:/RawDataCollection/raw_samples/PLB_Gate/raw_sample_storage2.h5
/raw_sample_all            frame_table  (typ->appendable,nrows->308581091,ncols->10,indexers->[index],dc->[time,GW_time,node_id,X,Y,Z,status,seq,rssi,lqi])

此外,我可以通过指示“”和“停止”来读取hdf文件的一部分,而不是“chunksize”:

代码语言:javascript
运行
复制
%%time
df = pd.read_hdf('raw_sample_storage2.h5','raw_sample_all', start=0,stop=300000)
print df.info()
print(df.head(5))

执行只需4秒,输出如下:

代码语言:javascript
运行
复制
<class 'pandas.core.frame.DataFrame'>
Int64Index: 300000 entries, 0 to 49999
Data columns (total 10 columns):
time       300000 non-null datetime64[ns]
GW_time    300000 non-null uint32
node_id    300000 non-null uint8
X          300000 non-null uint16
Y          300000 non-null uint16
Z          300000 non-null uint16
status     300000 non-null uint8
seq        300000 non-null uint8
rssi       300000 non-null int8
lqi        300000 non-null uint8
dtypes: datetime64[ns](1), int8(1), uint16(3), uint32(1), uint8(4)
memory usage: 8.9 MB
None
                 time   GW_time  node_id      X      Y      Z  status  seq  \
0 2013-10-22 17:20:58  39821761        3  20010  21716  22668       0   33   
1 2013-10-22 17:20:58  39821824        4  19654  19647  19241       0   33   
2 2013-10-22 17:20:58  39821888        1  16927  21438  22722       0   34   
3 2013-10-22 17:20:58  39821952        2  17420  22882  20440       0   34   
4 2013-10-22 17:20:58  39822017        3  20010  21716  22668       0   34   

   rssi  lqi  
0   -43   49  
1   -72   47  
2   -46   48  
3   -57   46  
4   -42   50  
Wall time: 4.26 s

注意到300000行只占用8.9MB内存,我尝试使用块大小以及start和stop:

代码语言:javascript
运行
复制
for df in pd.read_hdf('raw_sample_storage2.h5','raw_sample_all', start=0,stop=300000,chunksize = 3000):
    print df.info()
    print(df.head(5))

同样的MemoryError也会发生。

我不明白这里发生了什么,如果内部机制在某种程度上忽略了块/启动/停止,并试图将整个程序加载到RAM中,那么当MemoryError发生时,为什么内存使用量几乎没有增加(只有100 MB)?为什么执行只需要半个小时才能在进程开始时到达错误而没有明显的CPU使用呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-06-08 11:32:04

因此,迭代器的构建主要是为了处理where子句。PyTables返回子句为True的指示符的列表。这些是行号。在本例中,没有where子句,但我们仍然使用索引器,在本例中,索引器只是行列表上的np.arange

300行占用2.2GB。这对于windows 32位(通常是1GB左右的最大值)来说太大了。就64位而言,这没什么问题。

代码语言:javascript
运行
复制
In [1]: np.arange(0,300000000).nbytes/(1024*1024*1024.0)
Out[1]: 2.2351741790771484

因此,这应该通过切片语义来处理,这将使这只需占用少量的内存。问题打开了here

所以我建议你这么做。这里直接计算索引器,这提供了迭代器语义。

代码语言:javascript
运行
复制
In [1]: df = DataFrame(np.random.randn(1000,2),columns=list('AB'))

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

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

In [4]: nrows = store.get_storer('df').nrows

In [6]: chunksize = 100

In [7]: for i in xrange(nrows//chunksize + 1):
            chunk = store.select('df',
                                 start=i*chunksize,
                                 stop=(i+1)*chunksize)
            # work on the chunk    

In [8]: store.close()
票数 16
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30587026

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档