首页 > 解决方案 > 将镶木地板读入 Pandas 时如何解决内存问题

问题描述

我正在将 S3 中的文件读入 Pandas 数据框:这些文件是已分区的镶木地板。我将在 Lambda 中使用它,所以我需要对内存非常保守。当我运行以下语句时,内存不足:

pq.ParquetDataset(f's3://{path}', filesystem=s3).read_pandas().to_pandas()

但是,如果我运行以下命令,我很好:

pq.ParquetDataset(f's3://{path}', filesystem=s3)

然后如果添加它会再次中断:

pq.ParquetDataset(f's3://{path}', filesystem=s3).read_pandas()

未压缩的数据大小为 500 MB,我有 3 GB 的 RAM。有没有更高效的方式将一系列镶木地板拉入 Pandas 数据框?

我尝试过的其他东西:

这不起作用,因为如果它包含太长的字符串,它会中断:

for obj in bucket.objects.filter(Prefix=f'{prefix}'):
    obj = s3_resource.Object(buckey,obj.key)
    obj.download_fileobj(buffer)
    df = pd.read_parquet(buffer)

另一个不起作用的尝试:

def memory_optimized_pull(datekey, filter_column, filter_column_value):
    s3_resource = boto3.resource('s3')
    bucket_name = 'bn'
    bucket = s3_resource.Bucket(name=bucket_name)
    df_list = []
    for obj in bucket.objects.filter(Prefix=...):
        f = s3.open(f'{bucket_name}/{obj.key}')
        df = pq.read_table(f).to_pandas()
        df = df[df[filter_column] == filter_column_value]
        df_list.append(df)
    return pd.concat(df_list, ignore_index=True, sort=False)

标签: pythonpandasamazon-s3parquetpyarrow

解决方案


pq.ParquetDataset(f's3://{path}', filesystem=s3)没有用完内存的原因是它没有加载任何东西。它只是封装了如何读取数据集的细节,但在调用 read 之前实际上并没有做任何事情。

当您说未压缩的数据大小为 500 MB 时,您的意思是一旦加载到内存中?如果这是来自 s3 的文件大小,它可能是使用 snappy 压缩的(默认使用 pandas to_parquet)。

一般来说,parquet 适用于较大的数据集,而 AWS Lambda 并不是较重的 ETL 作业的最佳选择。


推荐阅读