python - 将镶木地板读入 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)
解决方案
pq.ParquetDataset(f's3://{path}', filesystem=s3)
没有用完内存的原因是它没有加载任何东西。它只是封装了如何读取数据集的细节,但在调用 read 之前实际上并没有做任何事情。
当您说未压缩的数据大小为 500 MB 时,您的意思是一旦加载到内存中?如果这是来自 s3 的文件大小,它可能是使用 snappy 压缩的(默认使用 pandas to_parquet
)。
一般来说,parquet 适用于较大的数据集,而 AWS Lambda 并不是较重的 ETL 作业的最佳选择。
推荐阅读
- html - iframe 网站拒绝连接,x-frame-options 被拒绝
- javascript - 你能从远程托管的 iframe 中检测字体吗?
- java - SQL Polybase 可以从 Azure datalake gen2 读取数据吗?
- javascript - Bootstrap Carousel White-Background in between Slides
- git - 将本地主分支与远程分支合并后,是否应该将其推送回远程?
- c# - 在 BizTalk 业务流程中处理 SOAP 异常
- javascript - 在这两个代码块中使用和省略关键字“await”有什么区别?
- c++ - 是否通过未定义的“函数”左值调用“noexcept 函数”?
- php - 从 PHP 循环组织 JSON
- python - 找到具有最大总和的从根到叶的路径 - 无法比较问题