通常,我们需要解析大型csv文件,只选择符合特定标准的行来加载dataframe。但是,对于大于内存的文件,我们不能简单地在dataframe中加载它并选择需要的文件。解决方案是用块解析csv文件,只将需要的行追加到dataframe中。在本文中,我还提供了一些工具来了解内存的一般用法。
首先,一些方法来确定我们需要的不同大小(内存、csv、dataframe)。
查找可用的RAM:
为此,我们需要一个名为psutil的库
pip install psutil
并使用以下方法获取
import psutil
svmem = psutil.virtual_memory()
print(svmem.available)
获取csv大小:
为此,我们将使用os库。我们还可以遍历一个文件夹,如果你的数据集被分割成几个文件,我们可以得到文件的累积大小:
import os
# only one file dataset:
os.path.getsize('./dataset.csv')
# same but for a folder containing several files:
total_filesize = 0
for filename in os.listdir('./dataset_folder/'):
total_filesize = total_filesize + os.path.getsize(filename)
获取dataframe的大小:
以下命令返回数据帧df占用的内存大小,包括其索引。
df.memory_usage(index=True).sum()
另一个选择是使用sys库如下:
import sys
sys.getsizeof(df)
处理csv文件
让我们阅读csv的前几行,看看它需要多少内存。
df_sample = pd.read_csv(‘./dataset.csv’, nrows=10)
df_sample_size = df_sample.memory_usage(index=True).sum()
在下面的示例中,我将使用1Gb的RAM进行处理,如果我的结果dataframe变得太大而无法存储在内存中,我将在处理过程中提醒我。
为此,我们使用chunksize和iterator参数,它决定了每次迭代读取的行数:
# define a chunksize that would occupy a maximum of 1Gb
# we divide by 10 because we have selected 10 lines in our df_sample
# we then get the integer part of the result
my_chunk = (1000000000 / df_sample_size)/10
my_chunk = int(my_chunk//1)
# create the iterator
iter_csv = pd.read_csv(
‘./dataset.csv’,
iterator=True,
chunksize=my_chunk)
# concatenate according to a filter to our result dataframe
df_result = pd.concat(
[chunk[chunk['my_field']>10]
for chunk in iter_csv])
在连接中,我们传递我们想要应用于数据的过滤器,以仅保留与此过滤器匹配的行。在此示例中,我们希望保留my_field列的值大于10的行。但是您可以使用任何经典的pandas方式过滤数据。
下面的完整代码,所以你不需要定义上面的Python代码片段:
import psutil
import pandas as pd
import csv
svmem = psutil.virtual_memory()
print (svmem.available)
PATH = r”C:\tmp\dataset\tf_train.csv”
df_sample = pd.read_csv(PATH, nrows=10)
df_sample_size = df_sample.memory_usage(index=True).sum()
print (df_sample_size)
print (df_sample)
# define a chunksize that would occupy a maximum of 1Gb
# we divide by 10 because we have selected 10 lines in our df_sample
my_chunk = (1000000000 / df_sample_size)/10
my_chunk = int(my_chunk//1) # we get the integer part
print (my_chunk)
# create the iterator
iter_csv = pd.read_csv(
PATH,
iterator=True,
chunksize=my_chunk)
# concatenate according to a filter to our result dataframe
df_result = pd.concat(
[chunk[chunk[‘n3’]>0]
for chunk in iter_csv])
print (df_result)