2017-07-11 7 views
6

मेरे पास boto3 (1.4.4), pyarrow (0.4.1) और pandas (0.20.3) का उपयोग करके इसे प्राप्त करने का एक हैकी तरीका है।पी 3 के माध्यम से एक पांडस डेटाफ्रेम के रूप में एस 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() 

एक आकर्षण की तरह दोनों काम करते हैं। अब मैं एक एस 3 बाल्टी में संग्रहीत फ़ाइलों के साथ एक ही दूरस्थ रूप से प्राप्त करना चाहता हूं। मुझे उम्मीद थी कि कुछ इस तरह काम करेगा:

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

लेकिन यह नहीं है:

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

pyarrow's documentation अच्छी तरह से पढ़ने के बाद, इस at the moment संभव प्रतीत नहीं होता।

S3 से एक एकल फाइल को पढ़ने और एक पांडा 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() 

और यहाँ मेरी hacky, नहीं-तो-अनुकूलित, समाधान से एक पांडा dataframe बनाने के लिए एक एस 3 फ़ोल्डर पथ:

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) 

क्या यह हासिल करने का एक बेहतर तरीका है? शायद पियरो का उपयोग कर पांडा के लिए कुछ प्रकार का कनेक्टर? मैं pyspark का उपयोग करने से बचना चाहता हूं, लेकिन यदि कोई अन्य समाधान नहीं है, तो मैं इसे ले जाऊंगा।

+0

क्या आप उन्हें दस्तावेज़ के साथ पढ़ने पर विचार करते हैं? मैं दो लाइनों में ऐसा करने में सक्षम हूं। – user32185

उत्तर

2

आप dask से s3fs का उपयोग कर सकते हैं जो s3 के लिए एक फाइल सिस्टम इंटरफ़ेस लागू करता है। तो फिर तुम इतने तरह ParquetDataset की फाइल सिस्टम तर्क का उपयोग कर सकते हैं:

import s3fs 
s3 = s3fs.S3FileSystem() 
dataset = pq.ParquetDataset('s3n://dsn/to/my/bucket', filesystem=s3) 
2

आप के रूप yjk21 द्वारा प्रस्तावित s3fs मॉड्यूल का उपयोग करना चाहिए। हालांकि ParquetDataset को कॉल करने के परिणामस्वरूप आपको एक pyarrow.parquet.ParkquetDataset ऑब्जेक्ट मिलेगा। पांडस डेटाफ्रेम प्राप्त करने के लिए आप इसे .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() 
संबंधित मुद्दे