将大于内存的csv文件过滤到Pandas数据帧-csv文件

将大于内存的csv文件过滤到Pandas数据帧

通常,我们需要解析大型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)

推荐阅读