6

我有一个大熊猫数据框(大小 = 3 GB):

x = read.table('big_table.txt', sep='\t', header=0, index_col=0)

因为我在内存限制下工作,所以我对数据框进行了子集化:

rows = calculate_rows() # a function that calculates what rows I need
cols = calculate_cols() # a function that calculates what cols I need
x = x.iloc[rows, cols]

计算行和列的函数并不重要,但它们肯定是原始行和列的较小子集。但是,当我执行此操作时,内存使用量会增加很多!最初的目标是将内存占用减少到 3GB 以下,但内存使用量却远远超过 6GB。

我猜这是因为 Python 在内存中创建了数据帧的本地副本,但没有清理它。可能还有其他事情正在发生......所以我的问题是我如何子集一个大型数据框并清理空间?我找不到选择行/列的函数。

我已经阅读了很多堆栈溢出,但在这个主题上找不到太多。可能是我没有使用正确的关键字,所以如果您有建议,那也可能会有所帮助。谢谢!

4

2 回答 2

8

你最好做这样的事情:

指定usecols首先选择您想要的列read_csv,请参见此处

然后分块读取文件,看这里,如果你想要的行被选择,将它们分流,最后连接结果。

伪代码ish:

reader = pd.read_csv('big_table.txt', sep='\t', header=0, 
                     index_col=0, usecols=the_columns_i_want_to_use, 
                     chunksize=10000)

df = pd.concat([ chunk.iloc[rows_that_I_want_] for chunk in reader ])

这将具有恒定的内存使用量(块的大小)

加上所选行的使用 x 2,当您在连接后连接行时会发生这种情况,使用将下降到所选行的使用

于 2013-10-30T17:50:45.070 回答
4

我遇到了类似的问题,我在加载之前通过过滤数据解决了它。当您使用 read.table 读取文件时,您会将整个文件加载到 DataFrame 中,并且可能还会将整个文件加载到内存中,或者由于使用了不同的类型而出现了一些重复,所以这是使用的 6GB。

您可以制作一个生成器来逐行加载文件的内容,我假设它是基于行的数据,一条记录是 big_table.txt 中的一行和一行,所以

def big_table_generator(filename):
    with open(filename, 'rt') as f:
        for line in f:
            if is_needed_row(line):   #Check if you want this row
                #cut_columns() return a list with only the selected columns
                record = cut_columns(line)    
                yield column


gen = big_table_generator('big_table.txt')
df = pandas.DataFrame.from_records(list(gen))

请注意 list(gen)、pandas 0.12 和以前的版本不允许生成器,因此您必须将其转换为列表,以便生成器提供的所有数据都放在内存中。0.13 将在内部做同样的事情。此外,您需要两倍的数据内存,一个用于加载数据,另一个用于将其放入 pandas NDframe 结构。

您还可以使生成器从压缩文件中读取,使用 python 3.3 gzip 库仅解压缩所需的块。

于 2013-10-30T11:59:20.303 回答