Lambda FunctionでExcelファイルからCSVファイルを作成してみた
データ分析におけるデータソースは、DB以外にもテキストファイルの構造化データを利用することが多くあります。
仮にデータがExcelファイルで管理されている場合、多くの場合でファイルフォーマットの変換が必要になると思います。 *1まずは、データ生成元でCSVファイルを作成すればいいと思いますが、仮にAWS側でExcelファイルをCSVファイルにする場合..というのが本エントリです。
ということで、今回はLambda Functionにて、ExcelファイルからCSVファイルを作成してみたいと思います。Lambda Function以外にも検討できるサービスはありますし、Lambda Functionの実行時間は最長15分という点についてはご留意ください。
ここでは、Lambda FunctionはS3トリガーでの起動を想定しています。以下のようなイメージです。
今回のやってみた環境は、SAMテンプレートにして本エントリの最後にはっておきました。
やってみた
PythonでExcelを扱うために、ここではopenpyxlライブラリを利用します。openpyxl
はPythonの標準ライブラリには含まれていないので個別に取得します。また、Lambda Functionで外部ライブラリが呼び出しできるよう、ここではLambda Layerにて取り込みを行います。
openpyxlダウンロード
以下のコマンドでインストールディレクトリを指定して、パッケージのダウンロード、アーカイブします。
$ mkdir python $ pip install -t ./python openpyxl $ zip -r openpyxl.zip python
Lambda Layer作成
ここではAWS CLIにてLambda Layerを作成します。
$ aws lambda publish-layer-version \ --layer-name xls-to-csv \ --zip-file fileb://openpyxl.zip \ --compatible-runtimes python3.6 python3.7 python3.8
Lambda Layerが作成できました。
Lambda Function作成
Lambda Functionのコードは以下となります。
import os import boto3 import openpyxl import csv s3 = boto3.resource('s3') s3_client = boto3.client('s3') def lambda_handler(event, context): data_target_bucket = os.environ['DATA_TARGET_BUCKET'] # 環境変数より変換後データ保存先バケット取得 data_source_bucket = event['Records'][0]['s3']['bucket']['name'] # Lambda関数呼び出し元バケット名 data_source_key = event['Records'][0]['s3']['object']['key'] # オブジェクトキー取得 # カレントディレクトリ移動 os.chdir('/tmp') # S3にPUTされたExcelファイルダウンロード source_bucket_obj = s3.Bucket(data_source_bucket) source_bucket_obj.download_file(data_source_key, data_source_key) # Excel Book/Worksheetオープン wb = openpyxl.load_workbook(data_source_key) ws = wb.worksheets[0] # CSVファイル名 csv_filename = os.path.splitext(os.path.basename(data_source_key))[0] + '.csv' # CSVファイル作成 with open(csv_filename, 'w', newline="") as csvfile: writer = csv.writer(csvfile) for row in ws.rows: # Excel行データを取得(リスト形式) row_data = [cell.value for cell in row] # CSV書き込み writer.writerow(row_data) # CSVファイルアップロード s3_client.upload_file(csv_filename, data_target_bucket, csv_filename) return None
シンプルにExcel行データをCSVファイルに書き込むようなつくりです。Excelワークブックのシート数の考慮や、データ保存先となるS3の構成などは要件にあわせ変更ください。(ハイライト部)
Lambda Functionでは環境変数DATA_TARGET_BUCKET
にて、CSVファイル格納先となるS3バケット(例:test-target-data-bucket
)を指定します。指定したS3にもアクセス可能な権限(ロール/ポリシー)をLambda Functionに付与してください。
S3アップロード
今回はこちらのExcelファイルを利用して、ExcelファイルからCSVファイルを作成したいと思います。
Excelファイル内容
ExcelファイルをS3にアップします。Excel、CSVファイル格納バケットを環境変数に設定し、CSVファイル格納先は、Lambda Function実行(S3トリガー発生)前後で、宛先バケットをリストしています。
# CSV格納先S3バケット $ S3_TARGET_BUCKET=s3://<バケット名> # Excel格納先S3バケット $ S3_SOURCE_BUCKET=s3://<バケット名> $ aws s3 ls ${S3_TARGET_BUCKET} $ ls -l b2015_gom1j_53.xlsx $ aws s3 cp b2015_gom1j_53.xlsx ${S3_BUCKET} $ aws s3 ls ${S3_SOURCE_BUCKET} $ aws s3 ls ${S3_TARGET_BUCKET} 2020-08-24 11:40:12 22806 b2015_gom1j_53.csv
上記の通り、CSVファイルの作成が確認できました。作成されたCSVファイルの内容は以下です。
CSVファイル内容
さいごに
ExcelファイルからCSVファイルの作成はできました。ただし、これだけで分析の前処理が完成しているとは言えませんので、要件にあわあせて調整が必要になると思います。Lambda FunctionでExcelファイルからCSVファイルを作成するなら..といった感じで参考にしていただければ幸いです。
今回のやってみた環境のSAMテンプレートは以下になります。SAM自体の使い方についてはこちらを参考にしてみてください。
脚注
- Amazon QuickSightだけ利用できればいいといった要件なら、Excelファイルのままでも扱えると思いますが、AWS Glueなどを使って、RDSなどに格納しておきたいといった要件には、ファイルフォーマットの変換が必要になってきます。 ↩