将Dataframe直接保存为csv文件到s3 Python

207

我有一个pandas DataFrame,想将其上传到新的CSV文件中。问题是我不想在传输到s3之前将文件保存在本地。是否有类似于to_csv的方法可以直接将DataFrame写入s3?我正在使用boto3。
以下是我目前的代码:

import boto3
s3 = boto3.client('s3', aws_access_key_id='key', aws_secret_access_key='secret_key')
read_file = s3.get_object(Bucket, Key)
df = pd.read_csv(read_file['Body'])

# Make alterations to DataFrame

# Then export DataFrame to CSV through direct transfer to s3

14
df.to_csv('s3://mybucket/dfs/somedf.csv')的意思是将DataFrame对象保存为CSV格式,并上传到名为"mybucket"的Amazon S3存储桶中的"dfs"文件夹下,文件名为"somedf.csv"。请参考https://dev59.com/zloT5IYBdhLWcg3w0B-_#56275519了解更多信息。 - Peter Berg
我喜欢这个解决方案。非常紧凑、简洁和优雅!谢谢分享!! - ASH
@PeterBerg,它给了我访问被拒绝的错误 :( - Raksha
15个回答

1
from io import StringIO
import boto3
#Creating Session With Boto3.
session = boto3.Session(
aws_access_key_id='<your_access_key_id>',
aws_secret_access_key='<your_secret_access_key>'
)
#Creating S3 Resource From the Session.
s3_res = session.resource('s3')
csv_buffer = StringIO()
df.to_csv(csv_buffer)
bucket_name = 'stackvidhya'
s3_object_name = 'df.csv'
s3_res.Object(bucket_name, s3_object_name).put(Body=csv_buffer.getvalue())
print("Dataframe is saved as CSV in S3 bucket.")

3
你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community

0
针对可能在使用S3FS或fsspec时遇到问题的用户:
你需要为每个库创建一个层并将它们插入到你的Lambda中。
你可以在此处找到如何创建一个层。

0
另一个选择是使用cloudpathlib来完成此操作,它支持S3,Google Cloud Storage和Azure Blob Storage。请参见下面的示例。
import pandas as pd
from cloudpathlib import CloudPath

# read data from S3
df = pd.read_csv(CloudPath("s3://covid19-lake/rearc-covid-19-testing-data/csv/states_daily/states_daily.csv"))

# look at some of the data
df.head(1).T.iloc[:10]
#>                                       0
#> date                           20210307
#> state                                AK
#> positive                        56886.0
#> probableCases                       NaN
#> negative                            NaN
#> pending                             NaN
#> totalTestResultsSource  totalTestsViral
#> totalTestResults              1731628.0
#> hospitalizedCurrently              33.0
#> hospitalizedCumulative           1293.0

# writing to S3
with CloudPath("s3://bucket-you-can-write-to/data.csv").open("w") as f:
    df.to_csv(f)

CloudPath("s3://bucket-you-can-write-to/data.csv").exists()
#> True

请注意,由于pandas处理传递给它的路径/句柄的方式,您不能直接调用df.to_csv(CloudPath("s3://drivendata-public-assets/test-asdf2.csv"))。相反,您需要打开文件进行写入,并将该句柄直接传递给to_csv
这带来了一些额外的好处,例如设置特定选项不同的身份验证机制或保持持久缓存,以便您不必总是从S3重新下载。

0
为了有效地处理大文件,您也可以使用开源S3兼容的MinIO,例如在我的这个函数中,使用其minioPython客户端包
import minio
import os
import pandas as pd

minio_client = minio.Minio(..)

def write_df_to_minio(df, 
                    minio_client, 
                    bucket_name, 
                    file_name="new-file.csv",
                    local_temp_folder="/tmp/", 
                    content_type="application/csv",
                    sep=",",
                    save_row_index=False):

    df.to_csv(os.path.join(local_temp_folder, file_name), sep=sep, index=save_row_index)
    
    minio_results = minio_client.fput_object(bucket_name=bucket_name,
                                             object_name=file_name,
                                             file_path=os.path.join(local_temp_folder, file_name),
                                             content_type=content_type)

    assert minio_results.object_name == file_name


-5
我从S3存储桶中读取了一个包含两列的CSV文件,并将其内容放入Pandas数据帧中。
例如:

config.json

{
  "credential": {
    "access_key":"xxxxxx",
    "secret_key":"xxxxxx"
}
,
"s3":{
       "bucket":"mybucket",
       "key":"csv/user.csv"
   }
}

cls_config.json

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import json

class cls_config(object):

    def __init__(self,filename):

        self.filename = filename


    def getConfig(self):

        fileName = os.path.join(os.path.dirname(__file__), self.filename)
        with open(fileName) as f:
        config = json.load(f)
        return config

cls_pandas.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import pandas as pd
import io

class cls_pandas(object):

    def __init__(self):
        pass

    def read(self,stream):

        df = pd.read_csv(io.StringIO(stream), sep = ",")
        return df

cls_s3.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import boto3
import json

class cls_s3(object):

    def  __init__(self,access_key,secret_key):

        self.s3 = boto3.client('s3', aws_access_key_id=access_key, aws_secret_access_key=secret_key)

    def getObject(self,bucket,key):

        read_file = self.s3.get_object(Bucket=bucket, Key=key)
        body = read_file['Body'].read().decode('utf-8')
        return body

test.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from cls_config import *
from cls_s3 import *
from cls_pandas import *

class test(object):

    def __init__(self):
        self.conf = cls_config('config.json')

    def process(self):

        conf = self.conf.getConfig()

        bucket = conf['s3']['bucket']
        key = conf['s3']['key']

        access_key = conf['credential']['access_key']
        secret_key = conf['credential']['secret_key']

        s3 = cls_s3(access_key,secret_key)
        ob = s3.getObject(bucket,key)

        pa = cls_pandas()
        df = pa.read(ob)

        print df

if __name__ == '__main__':
    test = test()
    test.process()

4
把英语翻译成中文。只返回翻译后的文本:请不要只发布答案,还需解释说明。 - sjaustirni
制作这样复杂(对于 Python 新手而言)的解决方案有什么优势吗? - Javier Lopez Tomas
1
这段代码从S3读取文件,问题是如何将数据框写入S3。 - Damian Satterthwaite-Phillips

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接