ネストのあるjsonデータをpandasでフラットに扱う
ネストの深いデータ
簡単にデータを取り込んで扱えるpandasだが、下記のようにネストが深いと勝手が悪い。
nested.json { col1:{row1:1,row2:x,row3:{id:1,age:20,data:{a:1,b:2}}}, col2:{row1:2,row2:y,row3:{id:2,age:23,data:{a:3,b:4}}} }
そのままとりこむとこんな感じ
import pandas as pd f = open(filepath, 'r') data = json.load(f) df = pd.DataFrame(data)
col1 | col2 | |
row1 | 1 | 2 |
row2 | x | y |
row3 | {id:1,age:20,data:{a:1,b:2}} | {id:2,age:23,data:{a:3,b:4}} |
データの転置
列ごとに1件とするデータだとわかる。そのままだと扱いづらいので転置する。
df_t = df.T
row1 | row2 | row3 | |
col1 | 1 | x | {'age': '20', 'data': {'b': '2', 'a': '1'}, 'id': '1'} |
col2 | 2 | y | {'age': '23', 'data': {'b': '4', 'a': '3'}, 'id': '2'} |
json_normalizeでフラットにする
あとはrow3の要素をそれぞれ取り出して一覧したい。
そんなときはjson_normalizeを利用すると便利。
import pandas as pd from pandas.io.json import json_normalize def extract_data(d): result = json_normalize(d) result = result.iloc[0, :] # seriesに変換 return result # seriesで返すこと f = open(filepath, 'r') data = json.load(f) df = pd.DataFrame(data) df_t = df.T df_flatten = pd.concat([df_t, df_t.row3.apply(extract_data)], axis=1)
データフレームに入れるとrow3が辞書型の文字列として取り込まれるので、
作成した関数内でjson_normalizeを使ってデータフレームに変換。
そのままだと元のdf_tに返せないのでseriesに変換して渡す。
pd.concatで元のdf_tとrow3のデータから作ったデータフレームをくっつける。
これでめでたく一つのフラットなデータフレームとして扱える。
row1 | row2 | row3 | age | data.a | data.b | id | |
col1 | 1 | x | {'age': '20', 'data': {'b': '2', 'a': '1'}, 'i... | 20 | 1 | 2 | 1 |
col2 | 2 | y | {'age': '23', 'data': {'b': '4', 'a': '3'}, 'i... | 23 | 3 | 4 | 2 |
まだ試していないけれど、もっとネストが深くても同じ要領で操作を繰り返せばなんとかなりそう。