note.nkmk.me

pandasのjson_normalizeで辞書のリストをDataFrameに変換

Date: 2018-05-14 / Modified: 2018-05-25 / tags: Python, pandas, JSON
このエントリーをはてなブックマークに追加

pandas.io.json.json_normalize()関数を使うと共通のキーをもつ辞書のリストをpandas.DataFrameに変換できる。

辞書のリストはpandas.read_json()pandas.DataFrame.to_read()において引数orient='records'で読み書きできる形式。

Web APIなどで取得できるJSONによく使われる形式なので、それをpandas.DataFrameに変換できるのは非常に便利。

ここでは以下の内容について説明する。

  • pandas.io.json.json_normalize()の基本的な使い方
  • JSON文字列・ファイルの一部を読み込み
スポンサーリンク

pandas.io.json.json_normalizeの基本的な使い方

以下のような辞書のリストを例とする。

import pandas as pd

l = [{'name': 'Alice', 'age': 25, 'id': {'x': 2, 'y': 8}},
     {'name': 'Bob', 'id': {'x': 10, 'y': 4}}]

これをpandas.io.json.json_normalize()の第一引数に渡す。

df = pd.io.json.json_normalize(l)

print(df)
#     age  id.x  id.y   name
# 0  25.0     2     8  Alice
# 1   NaN    10     4    Bob

辞書のキーkeyが列ラベル(列名)になる。

キーが存在しない場合は欠損値NaN

辞書の値valueに辞書がある場合(ネストしている場合)は、<親のキー>.<子のキー>が列名となる。このセパレータ.は引数sepで変更できる。

df_sep = pd.io.json.json_normalize(l, sep='-')

print(df_sep)
#     age  id-x  id-y   name
# 0  25.0     2     8  Alice
# 1   NaN    10     4    Bob

以下のように辞書の値がさらに辞書のリストになっている場合。

ll = [{'label': 'X',
       'info' : {'n': 'nx', 'm': 'mx'},
       'data': [{'a': 1, 'b': 2},
                {'a': 3, 'b': 4}]},
      {'label': 'Y',
       'info' : {'n': 'ny', 'm': 'my'},
       'data': [{'a': 10, 'b': 20},
                {'a': 30, 'b': 40}]}]

引数record_pathでキーを指定すると、そのキーに対応する値を辞書のリストとして変換する。

df_l = pd.io.json.json_normalize(ll, record_path='data')

print(df_l)
#     a   b
# 0   1   2
# 1   3   4
# 2  10  20
# 3  30  40

他のキーの値も変換したい場合は引数metaで指定する。

値が辞書の場合(ネストしている場合)はリスト[<親のキー>, <子のキー>]で子のキーを指定する。デフォルトでは<親のキー>.<子のキー>が列名となるが、ここでも引数sepでセパレータを変更できる。

df_lm = pd.io.json.json_normalize(ll, record_path='data',
                                  meta=['label', ['info', 'n'], ['info', 'm']],
                                  sep='_')

print(df_lm)
#     a   b label info_n info_m
# 0   1   2     X     nx     mx
# 1   3   4     X     nx     mx
# 2  10  20     Y     ny     my
# 3  30  40     Y     ny     my

JSON文字列・ファイルの一部を読み込み

辞書のリストはWeb APIなどで取得できるJSONによくある形式だと最初に書いたが、このままの形で取得できることは少なく、JSON文字列・ファイルの一部(要素)を抽出する必要がある場合が多い。

以下の文字列を例に説明する。

import pandas as pd
import json

s = '{"OTHER": "x", "DATA": [{"name":"Alice","age":25},{"name":"Bob","age":42}]}'

標準ライブラリのjsonモジュールのjson.loads()で文字列を辞書に変換する。JSONファイルを読み込む場合はjson.load()を使う。

d = json.loads(s)

print(d)
# {'OTHER': 'x', 'DATA': [{'name': 'Alice', 'age': 25}, {'name': 'Bob', 'age': 42}]}

print(type(d))
# <class 'dict'>

辞書からpandas.DataFrameとして読み込みたい部分(辞書のリスト)を抽出する。ネストが深い場合は[キー名][キー名]のように繰り返す。

l_target = d['DATA']

print(l_target)
# [{'name': 'Alice', 'age': 25}, {'name': 'Bob', 'age': 42}]

print(type(l_target))
# <class 'list'>

pandas.io.json.json_normalize()pandas.DataDrameに変換。

df = pd.io.json.json_normalize(l_target)

print(df)
#    age   name
# 0   25  Alice
# 1   42    Bob

まとめて書いてもOK。

df2 = pd.io.json.json_normalize(json.loads(s)['DATA'])

print(df2)
#    age   name
# 0   25  Alice
# 1   42    Bob

辞書のリストではないJSON形式を文字列・ファイルから抽出して読み込む場合については以下の記事を参照。

スポンサーリンク
シェア
このエントリーをはてなブックマークに追加

関連カテゴリー

関連記事