Tôi có cách hacky để đạt được điều này bằng cách sử dụng boto3
(1.4.4), pyarrow
(0.4.1) và pandas
(0.20.3).Làm thế nào để đọc một danh sách các tập tin gỗ từ S3 như một khung dữ liệu gấu trúc bằng cách sử dụng pyarrow?
Thứ nhất, tôi có thể đọc một file gỗ đơn tại địa phương như thế này:
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()
tôi cũng có thể đọc một thư mục của file gỗ tại địa phương như thế này:
import pyarrow.parquet as pq
dataset = pq.ParquetDataset('parquet/')
table = dataset.read()
df = table.to_pandas()
Cả hai công việc giống như một nét duyên dáng. Bây giờ tôi muốn đạt được cùng một từ xa với các tập tin được lưu trữ trong một thùng S3. Tôi đã hy vọng rằng một cái gì đó như thế này sẽ làm việc:
dataset = pq.ParquetDataset('s3n://dsn/to/my/bucket')
Nhưng nó không:
OSError: Passed non-file path: s3n://dsn/to/my/bucket
Sau khi đọc pyarrow's documentation triệt để, điều này dường như không thể at the moment. Vì vậy, tôi bước ra với các giải pháp sau đây:
Đọc một tập tin duy nhất từ S3 và nhận được một dataframe gấu trúc:
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()
Và đây tôi hacky, không quá tối ưu hóa, giải pháp để tạo ra một dataframe gấu trúc từ đường dẫn thư mục 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)
Có cách nào tốt hơn để đạt được điều này không? Có lẽ một số loại kết nối cho gấu trúc bằng cách sử dụng pyarrow? Tôi muốn tránh sử dụng pyspark
, nhưng nếu không có giải pháp nào khác, thì tôi sẽ lấy nó.
Bạn đã cân nhắc đọc chúng bằng dấu chấm chưa? Tôi có thể làm tương tự trong hai dòng. – user32185