ドーモ。ホクソエムです。更新が久しくなってしまいました。ホクソエムでは現在、Amazon Web Service (AWS)を利用していないのですが、本職の方でS3に触れる機会があったので、RからS3への操作を行うためのパッケージ awe.s3 を紹介したいと思います。

ASW S3とは、AWSが提供するサービスの一つで、オンラインでのファイルストレージとして利用できます。ストレージするファイルの容量・種類は問わないので、一時的なデータや画像の保存先として使われているのではないでしょうか。また、柔軟にアクセス制限やファイルのライフサイクル(自動的な削除)がかけられるのも特徴です。S3では、バケットと呼ばれるフォルダのような構造と、オブジェクト(データ)を管理します。

awe.s3パッケージは、数多くの便利なRパッケージを行っているROpenSciのメンバーでもあるThomas J. Leeperらが活動するcloudyrというRのチームが開発しています。cloudyrのリポジトリには、今回紹介するawe.s3のほか、同じAWSのサービスであるES2管理やLambdaのためのaws.ec2aws.lambdaなども含まれています。

https://github.com/cloudyr/aws.s3

awe.s3はCRANに登録されていますので、次のコマンドでインストールしましょう。また、S3の操作に必要なアクセスキーとIDは、IAM (Identity and Access Management) Management Consoleから発行しておいてください。

install.packages("aws.s3", dependencies = TRUE)
library(aws.s3)

アカウントとの紐付け

早速、ストレージしたファイルへのアクセスを行いたいところですが、まずはアクセスキーIDとシークレットキーを使った認証を行うことが必要です。

cloudyrが携わるAWS関係のRパッケージでは、Sys.setenv()で設定されている環境変数を利用します。これらが.Rprofile等に記載されていない場合は、コンソールでSys.setenv()を行いましょう。必要な情報は、アクセスキーID、シークレットキー、利用しているリージョン(地域)です。

# 環境変数の値を確認
Sys.getenv("AWS_DEFAULT_REGION")
# [1] ""

Sys.setenv("AWS_DEFAULT_REGION" = "<リージョン>", # us-east-2 など
           "AWS_ACCESS_KEY_ID" = "<アクセスキーID>",
           "AWS_SECRET_ACCESS_KEY" = "<シークレットキー>")

複数アカウントがある場合、AWSの発行するcredentialsファイルを使った署名を行うこともできます。これにはawe.s3インストール時に依存パッケージとしてインストールされるaws.signatureuse_credentials()を使います。

# defaultのアカウント情報を用いた署名
aws.signature::use_credentials()

# hoxouri ユーザのアカウント情報を利用する場合
aws.signature::use_credentials(profile = "hoxouri")

接続が成功しているかを確かめるため、バケットの一覧を表示してみます。

bucketlist()
#              Bucket             CreationDate
# 1 aws.s3.test170418 2017-04-18T04:35:22.000Z
# 2        hoxom-blog 2017-07-18T11:02:47.000Z

うまくできているようですね。

特定のバケットのオブジェクトを出力するにはget_bucket()を使います。

get_bucket("aws.s3.test170418")
# Bucket: aws.s3.test170418 
# 
# named list()

どうやらこのバケットにはまだ何も入っていないようです。

オブジェクト操作

それでは、バケットに対してオブジェクト(データ)を保存したり、バケット内のオブジェクトへの操作を行いましょう。awe.s3では、次のようなオブジェクト操作が可能です。

  • Rオブジェクト(.Rdata, .rds)の読み書き (s3save(), s3saveRDS())
  • R関数を使ったRへの読み書き (s3read_using(), s3write_using())
  • ローカルファイルのバケットへの保存 (put_object())
  • バケットからのローカルへの保存 (get_object())
  • バケット、オブジェクトの削除 (delete_bucket(), delete_object())

例として、mtcarsオブジェクト(データフレーム)をS3に保存します。Rオブジェクトとして保存したい時はs3save()で行います。

s3save(mtcars, bucket = "aws.s3.test170418", object = "mtcars.rds")

第一引数で対象のRオブジェクト、第二引数で対象のバケット名、第三引数のobject引数ではオブジェクト名を与えます。関数の実行後、コンソールには何も表示されませんが、エラーがでなければアップロードは成功しているはずです。改めてバケットの中身を出力してみましょう。

get_bucket("aws.s3.test170418")
# Bucket: aws.s3.test170418 
# 
# $Contents
# Key:            mtcars.rds 
# LastModified:   2017-07-18T11:33:04.000Z 
# ETag:           "1bf2269b855ca97b628582dc29962eb1" 
# Size (B):       1235 
# Owner:          suika1127 
# Storage class:  STANDARD

次はcsvをアップロードする例です。Rオブジェクトではなくcsvなどのファイルで保存したい時はreadr::write_csv()などの関数を使いテキストファイルにしておきましょう。またその際はput_object()を使い、ファイルのアップロードを行います。

mtcars %>% 
  readr::write_csv("sample_mtcars.csv")
put_object(file = "sample_mtcars.csv", 
           object = "sample_mtcars.csv", 
           # バケットにはフォルダを作ることができますが、bucket引数で指定(なければ作成される)できます
           bucket = "aws.s3.test170418/csv")

今度は保存したオブジェクトをRで利用可能な状態にします。対象がRオブジェクトであればs3loadreadrreadxlで読み込めるファイルであればs3read_using()を用います。

s3load("mtcars.rds", bucket = "aws.s3.test170418")
ls()
# [1] "mtcars"

s3read_using(readr::read_csv, object = "sample.csv", 
             bucket = "aws.s3.test170418/csv")

rdsファイルに保存したmtcarsオブジェクトが利用できるようになりました。

私も使い始めたばかりで、aws.s3パッケージの全てを紹介しきれませんが、基本的なことはできたかと思います。つどコンソールを叩かず、集計結果等を保存できる、データを引っ張ってこれるので便利ですね。

Enjoy!