pandas で DynamoDB からエクスポートしたデータを読み込む
個人的にAWSで運営しているサービスのデータを取り込んで統計を取りたくなったので作業手順のメモを残します。
DynamoDB からエクスポートしたデータを眺める
DynamoDBのデータは AWS Data Pipeline で S3 にエクスポートし、ダウンロードします。
{"userId":{"s":"Google-ABwppHFW〜"},"mapAttr":{"m":{}}}
{"userId":{"s":"Google-ABwppHFD〜"},"mapAttr":{"m":{"accessCount":{"n":"2"},"lastAccess":{"s":"2018-01-21T09:29:01.847Z"}}}}
{"userId":{"s":"Google-ABwppHEs〜"},"mapAttr":{"m":{"data1":{"n":"1772977"},"accessCount":{"n":"2"},"lastAccess":{"s":"2018-02-13T08:32:22.318Z"},"data2":{"m":{"data3":{"n":"2"}}}}}}
{"userId":{"s":"amzn1.ask.account.AFQ〜"},"mapAttr":{"m":{"data1":{"n":"2685460"},"accessCount":{"n":"8"},"lastAccess":{"s":"2018-04-17T00:38:09.553Z"},"data2":{"m":{"data4":{"n":"38000"}}}}}}
...
データは一部抜粋&加工。userIdをキーとして、mapAttrにオブジェクトを持つ形式です。
DynamoDBからエクスポートしたデータは1行ごとのJSONを繋げたテキストファイル(JSON Lines)になります。
pandas で読み込む
pandas には read_json で JSON を直接読み込む事ができますが、今回のような複雑な入れ子のJSONは読み込めません。
pandas.io.json.json_normalize を使用すると入れ子のキーを列に展開して dataframe に読み込む事ができます。
ただし、json_normalize は JSON Lines のファイルから直接読み込む事はできませんので、自前で1行ずつパースしてリストとして json_normalize に食わせます。
# coding: UTF-8
import json
import pandas as pd
from pandas.io.json import json_normalize
pd.set_option("display.max_colwidth", 1024)
with open('data') as f:
lines = f.readlines()
json_lines = map(lambda l: json.loads(l), lines)
df = pd.io.json.json_normalize(list(json_lines))
print(df.head(10))
userId.s mapAttr.m.accessCount.n mapAttr.m.accessCount.lastAccess.s mapAttr.m.data1.n mapAttr.m.data2.m.data3.n ...
0 Google-ABwppHFW〜 NaN NaN NaN NaN ...
1 Google-ABwppHFD〜 2 2018-01-21T09:29:01.847Z NaN NaN ...
2 Google-ABwppHEs〜 2 2018-02-13T08:32:22.318Z 1772977 2 ...
...
色々加工が必要かと思っていたのですがあっさり読み込めてしまいました。