如何使用pyarrow将S3中的一组parquet文件读取为pandas数据框架?

9 浏览
0 Comments

如何使用pyarrow将S3中的一组parquet文件读取为pandas数据框架?

我有一个使用boto3(1.4.4),pyarrow(0.4.1)和pandas(0.20.3)的方法来实现这个目标。

首先,我可以像这样在本地读取单个parquet文件:

import pyarrow.parquet as pq
path = 'parquet/part-r-00000-1e638be4-e31f-498a-a359-47d017a0059c.gz.parquet'
table = pq.read_table(path)
df = table.to_pandas()

我也可以像这样在本地读取一个parquet文件夹:

import pyarrow.parquet as pq
dataset = pq.ParquetDataset('parquet/')
table = dataset.read()
df = table.to_pandas()

这两种方法都非常好用。现在我想通过在S3存储桶中存储的文件来实现相同的功能。我希望像这样做是可行的:

dataset = pq.ParquetDataset('s3n://dsn/to/my/bucket')

但是它不起作用:

OSError: Passed non-file path: s3n://dsn/to/my/bucket

在仔细阅读了pyarrow的文档之后,目前似乎不可能实现 这种方法。所以我想出了以下解决方法:

从S3中读取单个文件并获取一个pandas dataframe:

import io
import boto3
import pyarrow.parquet as pq
buffer = io.BytesIO()
s3 = boto3.resource('s3')
s3_object = s3.Object('bucket-name', 'key/to/parquet/file.gz.parquet')
s3_object.download_fileobj(buffer)
table = pq.read_table(buffer)
df = table.to_pandas()

这是我用来从S3文件夹路径创建pandas dataframe的一种方法:

import io
import boto3
import pandas as pd
import pyarrow.parquet as pq
bucket_name = 'bucket-name'
def download_s3_parquet_file(s3, bucket, key):
    buffer = io.BytesIO()
    s3.Object(bucket, key).download_fileobj(buffer)
    return buffer
client = boto3.client('s3')
s3 = boto3.resource('s3')
objects_dict = client.list_objects_v2(Bucket=bucket_name, Prefix='my/folder/prefix')
s3_keys = [item['Key'] for item in objects_dict['Contents'] if item['Key'].endswith('.parquet')]
buffers = [download_s3_parquet_file(s3, bucket_name, key) for key in s3_keys]
dfs = [pq.read_table(buffer).to_pandas() for buffer in buffers]
df = pd.concat(dfs, ignore_index=True)

有更好的方法实现这个吗?也许是使用pyarrow的pandas连接器?我想避免使用pyspark,但如果没有其他解决方案,我会采用它。

0