JSON ファイルのデータを料理したい🍕
JSON ファイルに入っているデータを料理したい。そこで、Pandas へ JSON を読み込んで片付けよう!。
さて。
今までは、JSON の中身を覗いたり、ちょっとデータを追加したりする程度だったので Vlad Badea さんの超有能アプリケーション、JSON Editor で良かったのですが、今回は少々手の込んだことをする必要があるのでどうしようかなと。
Why Japanese people?
たしか、組み込み python module [1] にまさにそのものズバリ、json [2]というのがあったはず。json って基本的に dictionary なんだから、薄切りだろうと厚切りだろうと、Pandas へ JSON を読み込み どうとでも料理できる!
というわけで、さっそく、
Script 1
import json with open('data.json') as f: my_dict = json.load(f) my_dict
とやってみたら、いい感じで中身が見えたので、さてこれを slice で取り出して…
そうだ、Pandasだ!
と考え始めた時点で、いやまて、こんなことしなくても、list とか dictionary なら Pandas で読めたはず、と思って、ちょっと書き換えて、
Script 2
import json import pandas as pd #これを足して、 with open('data.json') as f: my_dict = json.load(f) df = pd.DataFrame(my_dict) #これも足して、 df.head() #どうかな?できたかな?
とやってみたら、一応 data frame にはなったものの、行列が逆です(*)。
そこで慌てず騒がず、df.transpose()
としてみたら、行がrecord、列がcolumn となって無事に目的を達成😄
(*) もちろんこれは元々のファイルのデータ構造に依りますが。 なお、JSONそのもののデータ構造の説明はIntroducing JSON (json.org)にあります。
ちょっと待てよ?
この時点で、もしかしてものすごく無駄なことをやっていたのではないかと嫌な予感がしたため、pandas のドキュメントを見に行ったところ、そのものズバリ、pandas.read_jsonという method が。
これを使えば、
Script 3a
df = pd.read_json('data.json').transpose()
の1行で済む話でした。😭
Cult Occult Coding™
本当のところ、JSONファイルと言ってもその構造はケースバイケースなので、以上の超大雑把な例がそのままピタリと決まる場合の方が少ないかと思います。
そういうわけで、実際にはちょっと書いてみて様子を見ながら修正することになると思いますが、そのときにどこをいじるか?
第一候補は、orient
パラメータです。
どのような状況でどんなパラメータが使えるかは Document [3]にちゃんと書いてありますが、とりあえず…
Script 3b
df = pd.read_json('data.json', orient='split') df = pd.read_json('data.json', orient='split').transpose() df = pd.read_json('data.json', orient='records') df = pd.read_json('data.json', orient='records').transpose() df = pd.read_json('data.json', orient='index') df = pd.read_json('data.json', orient='index').transpose() df = pd.read_json('data.json', orient='columns') df = pd.read_json('data.json', orient='columns').transpose() df = pd.read_json('data.json', orient='values') df = pd.read_json('data.json', orient='values').transpose() df = pd.read_json('data.json', orient='table') df = pd.read_json('data.json', orient='table').transpose()
あたりを試して見てください。運がよければどれかが「当たり」です🎉
理屈もなにもあったものではない。これが運任せ・神頼みの、人呼んでカルト・オカルト・コーディング ™ 😅
上の例だと、試行錯誤が 12 通り。毎分 1 通り試すとしても 15 分かかります。これを長いと見るか短いと見るか?
こういうとき、Google Colab や IDE であれば、スマホの予測変換のような感じで、「お前の書きたいコードはこれじゃないのかな?」とコードをサジェストしてくれるのでメチャメチャ便利です。
Don’t Reinvent the Wheel!
Pandas Love
始めから素直にPandasでやろうと思わなかったおかげで、思いつきの連鎖で時間の浪費。気がつかなかったら半日を無駄にするところでした。
そもそも、pandas. read_csv だってpandas. read_excel だって pandas.read_html だって pandas. read_sql だってあるのだから、pandas. read_json だってあるに決まっている(*)。不精をしないでまず始めにドキュメント[4]を見に行くべきでした。
(*) っていうか、Python が登場したのが 1980 年代末、Pandas が世に出たのが 2008 年。世界中の親切なエンジニアが寄ってたかって update を続けてきているのだから、生活に必要なものは既に大体揃っていると考える方が普通ですよね…。
実はExcelでも読める
これを言っては身もフタもありませんが、Excel は JSON を直接に読み込むことができます(マイクロソフトサイト「JSONファイルに接続する」)。
もっとも、個人的な感想ですが Excel の操作はちょっと複雑なような気がします。やはり素直に Pandas を使った方が楽かも?
One more thing…
JSON 関連だと、Python の dictionary もいきなり Pandas の DataFrame (以下「DF」)に読み込めます。
たとえば、ランチに出すサンドイッチのメニューを Script 4 のような dictionary (というか、single -> double quotation に変換すればほぼ JSON) で作ったとして、これも from_dict()
を使って簡単に Pandas の DF にすることができます(Script 5)。
Script 4
dict_lunch_menu = { 'spam': { 'choice_1': 'Classic', 'choice_2': 'Classic', 'choice_3': 'Classic', 'choice_4': 'Classic', 'choice_5': 'Light', 'choice_6': 'Light', 'choice_7': 'Light', 'choice_8': 'Light' }, 'ham': { 'choice_1': 'City', 'choice_2': 'City', 'choice_3': 'Country', 'choice_4': 'Country', 'choice_5': 'City', 'choice_6': 'City', 'choice_7': 'Country', 'choice_8': 'Country' }, 'egg': { 'choice_1': 'Fried', 'choice_2': 'Poached', 'choice_3': 'Fried', 'choice_4': 'Poached', 'choice_5': 'Fried', 'choice_6': 'Poached', 'choice_7': 'Fried', 'choice_8': 'Poached' } }
Script 5
df_lunch_menu = pd.DataFrame.from_dict(dict_lunch_menu) df_lunch_menu
元に戻したければ、pd.DataFrame.to_dict()
があるし(Script 6)。
Script 6
pd.DataFrame.to_dict(df_lunch_menu) {'egg': {'choice_1': 'Fried', 'choice_2': 'Poached', 'choice_3': 'Fried', 'choice_4': 'Poached', 'choice_5': 'Fried', 'choice_6': 'Poached', 'choice_7': 'Fried', 'choice_8': 'Poached'}, 'ham': {'choice_1': 'City', 'choice_2': 'City', 'choice_3': 'Country', 'choice_4': 'Country', 'choice_5': 'City', 'choice_6': 'City', 'choice_7': 'Country', 'choice_8': 'Country'}, 'spam': {'choice_1': 'Classic', 'choice_2': 'Classic', 'choice_3': 'Classic', 'choice_4': 'Classic', 'choice_5': 'Light', 'choice_6': 'Light', 'choice_7': 'Light', 'choice_8': 'Light'}}
何かしたいと思ったら
まずは Document を見に行くのは、Pandas の場合はとりわけ重要かもしれません。
ファイルの読み書き[4]、フォーマット変換[5]絡みで何かしたいときは、Document のページに行って、to_ナントカ
とか from_カントカ
などという調子で検索すれば大概なんとかなる感じ 👍
References
[1] Python documentation. Python Module Index ( Google翻訳 )
[2] Python documentation. JSON encoder and decoder ( Google翻訳 )
[3] pandas documentation. pandas.read_json ( Google翻訳 )
[4] pandas documentation. Input/output ( Google翻訳 )
[5] pandas documentation. pandas.DataFrame ( Google翻訳 )