我使用boto3
(1.4.4),pyarrow
(0.4.1)和pandas
(0.20.3)实现了这一目标。
首先,我可以像这样在本地读取一个实木复合地板文件:
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()
我还可以像这样在本地读取实木复合地板文件的目录:
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读取单个文件并获取熊猫数据框:
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文件夹路径创建熊猫数据框:
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的熊猫连接器?我想避免使用pyspark
,但是如果没有其他解决方案,那么我会接受。
您应该使用yjk21s3fs
建议的模块。但是,由于调用ParquetDataset的结果,您将获得pyarrow.parquet.ParquetDataset对象。要获取Pandas DataFrame,您宁愿将其应用于:.read_pandas().to_pandas()
import pyarrow.parquet as pq
import s3fs
s3 = s3fs.S3FileSystem()
pandas_dataframe = pq.ParquetDataset('s3://your-bucket/', filesystem=s3).read_pandas().to_pandas()
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句