pandas.DataFrameをJSON文字列・ファイルに変換・保存(to_json)

Posted: | Tags: Python, pandas, JSON

pandas.DataFrameのメソッドto_json()を使うと、pandas.DataFrameをJSON形式の文字列(str型)に変換したり、JSON形式のファイルとして出力(保存)したりできる。

ここでは以下の内容について説明する。そのほかの引数については上記の公式ドキュメントを参照。

  • pandas.DataFrame.to_json()の基本的な使い方
    • JSON形式の文字列に変換
    • JSON形式のファイルとして出力(保存)
      • ファイル圧縮: 引数compression
  • 形式を指定: 引数orient
    • split
    • records
      • JSON Lines.jsonl
    • index
    • columns(デフォルト)
    • values
    • table
  • 全角文字(日本語)などのUnicodeエスケープ: 引数force_ascii

JSONファイルの読み込みはpandas.read_json()

pandas.DataFrameを辞書(dict型)に変換したい場合はto_dict()メソッドを使う。

そのほかpandasでのCSVファイルやExcelファイルの読み書き(入出力)については以下の記事を参照。

また、pandasではなくPython標準ライブラリのjsonモジュールで辞書を整形してJSON形式のファイルや文字列に出力する方法は以下の記事を参照。

ここでは、例として以下のpandas.DataFrameを作成する。

import pandas as pd
import pprint
import json

df = pd.DataFrame({'col1': [1, 2, 3], 'col2': ['a', 'x', 'あ']},
                  index=['row1', 'row2', 'row3'])

print(df)
#       col1 col2
# row1     1    a
# row2     2    x
# row3     3    あ

pprintとjsonは出力を見やすくするため、および、確認のためにインポートしている。処理自体には必要ない。

pandas.DataFrame.to_jsonの基本的な使い方

JSON形式の文字列に変換

pandas.DataFrameからto_json()メソッドを呼び出すと、デフォルトでは以下のようにJSON形式の文字列(str型)に変換される。

print(df.to_json())
# {"col1":{"row1":1,"row2":2,"row3":3},"col2":{"row1":"a","row2":"x","row3":"\u3042"}}

print(type(df.to_json()))
# <class 'str'>

全角文字などの非ascii文字はUnicodeエスケープされる。引数force_ascii=FalseとするとUnicodeエスケープされない。後述。

Unicodeエスケープについては以下の記事を参照。

JSON形式のファイルとして出力(保存)

第一引数にパスを指定するとファイルとして保存される。パスを指定しない場合に出力される文字列がそのままファイルとして書き込まれる。

path = 'data/src/sample_from_pandas_columns.json'

df.to_json(path)

テキストファイルとして読み込んで中身を確認すると以下の通り。

with open(path) as f:
    s = f.read()
    print(s)
    print(type(s))
# {"col1":{"row1":1,"row2":2,"row3":3},"col2":{"row1":"a","row2":"x","row3":"\u3042"}}
# <class 'str'>

open()で読み込む場合、引数encoding='unicode-escape'とするとUnicodeエスケープシーケンス\uXXXXは対応する文字に変換される。

with open(path, encoding='unicode-escape') as f:
    s = f.read()
    print(s)
    print(type(s))
# {"col1":{"row1":1,"row2":2,"row3":3},"col2":{"row1":"a","row2":"x","row3":"あ"}}
# <class 'str'>

標準ライブラリjsonモジュールのjson.load()関数で辞書として読み込み。この場合、デフォルトでUnicodeエスケープシーケンス\uXXXXは対応する文字に変換される。

with open(path) as f:
    d = json.load(f)
    print(d)
    print(type(d))
# {'col1': {'row1': 1, 'row2': 2, 'row3': 3}, 'col2': {'row1': 'a', 'row2': 'x', 'row3': 'あ'}}
# <class 'dict'>

JSONファイルをpandas.DataFrameとして読み込む場合はpandas.read_json()関数を使う。この場合も、デフォルトでUnicodeエスケープシーケンス\uXXXXは対応する文字に変換される。

df_read = pd.read_json(path)
print(df_read)
#       col1 col2
# row1     1    a
# row2     2    x
# row3     3    あ

ファイル圧縮: 引数compression

pandasのバージョン0.21.0から追加された引数compressionを指定すると、ファイル出力時に圧縮することが可能。

'gzip', 'bz2', 'xz'のいずれかを指定する。

df.to_json('data/src/sample_from_pandas_columns.gz', compression='gzip')

形式を指定: 引数orient

引数orientによって、pandas.DataFrameの行ラベルindex、列ラベルcolumns、値valuesをどのようにJSONとして出力するかを指定できる。

ここでは、json.loads()で出力文字列を辞書に変換しpprint()で見やすく表示した結果も合わせて示す。

split

{index -> [index], columns -> [columns], data -> [values]}

print(df.to_json(orient='split'))
# {"columns":["col1","col2"],"index":["row1","row2","row3"],"data":[[1,"a"],[2,"x"],[3,"\u3042"]]}

pprint.pprint(json.loads(df.to_json(orient='split')))
# {'columns': ['col1', 'col2'],
#  'data': [[1, 'a'], [2, 'x'], [3, 'あ']],
#  'index': ['row1', 'row2', 'row3']}

records

[{column -> value}, ... , {column -> value}]

print(df.to_json(orient='records'))
# [{"col1":1,"col2":"a"},{"col1":2,"col2":"x"},{"col1":3,"col2":"\u3042"}]

pprint.pprint(json.loads(df.to_json(orient='records')), width=40)
# [{'col1': 1, 'col2': 'a'},
#  {'col1': 2, 'col2': 'x'},
#  {'col1': 3, 'col2': 'あ'}]

JSON Lines(.jsonl)

引数orient='recordsの場合、さらに引数lines=Trueとすると{column: value}ごとに改行された文字列となる。

print(df.to_json(orient='records', lines=True))
# {"col1":1,"col2":"a"}
# {"col1":2,"col2":"x"}
# {"col1":3,"col2":"\u3042"}

これにより、JSONが改行で区切られたJSON Lines(.jsonl)フォーマットの文字列やファイルを作成できる。

index

{index -> {column -> value}}

print(df.to_json(orient='index'))
# {"row1":{"col1":1,"col2":"a"},"row2":{"col1":2,"col2":"x"},"row3":{"col1":3,"col2":"\u3042"}}

pprint.pprint(json.loads(df.to_json(orient='index')))
# {'row1': {'col1': 1, 'col2': 'a'},
#  'row2': {'col1': 2, 'col2': 'x'},
#  'row3': {'col1': 3, 'col2': 'あ'}}

columns(デフォルト)

{column -> {index -> value}}

引数orientを省略した場合(デフォルト)はこの形式。

print(df.to_json(orient='columns'))
# {"col1":{"row1":1,"row2":2,"row3":3},"col2":{"row1":"a","row2":"x","row3":"\u3042"}}

pprint.pprint(json.loads(df.to_json(orient='columns')))
# {'col1': {'row1': 1, 'row2': 2, 'row3': 3},
#  'col2': {'row1': 'a', 'row2': 'x', 'row3': 'あ'}}

values

print(df.to_json(orient='values'))
# [[1,"a"],[2,"x"],[3,"\u3042"]]

pprint.pprint(json.loads(df.to_json(orient='values')))
# [[1, 'a'], [2, 'x'], [3, 'あ']]

table

データの構造scheme情報をもつ形式。

print(df.to_json(orient='table'))
# {"schema": {"fields":[{"name":"index","type":"string"},{"name":"col1","type":"integer"},{"name":"col2","type":"string"}],"primaryKey":["index"],"pandas_version":"0.20.0"}, "data": [{"index":"row1","col1":1,"col2":"a"},{"index":"row2","col1":2,"col2":"x"},{"index":"row3","col1":3,"col2":"\u3042"}]}

pprint.pprint(json.loads(df.to_json(orient='table')))
# {'data': [{'col1': 1, 'col2': 'a', 'index': 'row1'},
#           {'col1': 2, 'col2': 'x', 'index': 'row2'},
#           {'col1': 3, 'col2': 'あ', 'index': 'row3'}],
#  'schema': {'fields': [{'name': 'index', 'type': 'string'},
#                        {'name': 'col1', 'type': 'integer'},
#                        {'name': 'col2', 'type': 'string'}],
#             'pandas_version': '0.20.0',
#             'primaryKey': ['index']}}

全角文字(日本語)などのUnicodeエスケープ指定: 引数force_ascii

引数force_ascii=Falseとすると、全角文字(日本語)などがUnicodeエスケープされずにそのまま出力される。

print(df.to_json(force_ascii=False))
# {"col1":{"row1":1,"row2":2,"row3":3},"col2":{"row1":"a","row2":"x","row3":"あ"}}

これまでの例のようにデフォルト(省略した場合)はforce_ascii=TrueでUnicodeエスケープされる。

上でも示したが、標準ライブラリjsonモジュールのjson.load(), json.loads()関数やpandas.read_json()関数でJSON形式のファイルや文字列を読み込む場合は、Unicodeエスケープされた文字も対応する文字に正しく変換される。

with open(path) as f:
    d = json.load(f)
    print(d)
    print(type(d))
# {'col1': {'row1': 1, 'row2': 2, 'row3': 3}, 'col2': {'row1': 'a', 'row2': 'x', 'row3': 'あ'}}
# <class 'dict'>

df_read = pd.read_json(path)
print(df_read)
#       col1 col2
# row1     1    a
# row2     2    x
# row3     3    あ

open()でテキストファイルとして読み込む場合は、引数encoding='unicode-escape'とするとUnicodeエスケープシーケンス\uXXXXは対応する文字に変換される。

with open(path) as f:
    s = f.read()
    print(s)
    print(type(s))
# {"col1":{"row1":1,"row2":2,"row3":3},"col2":{"row1":"a","row2":"x","row3":"\u3042"}}
# <class 'str'>

with open(path, encoding='unicode-escape') as f:
    s = f.read()
    print(s)
    print(type(s))
# {"col1":{"row1":1,"row2":2,"row3":3},"col2":{"row1":"a","row2":"x","row3":"あ"}}
# <class 'str'>

関連カテゴリー

関連記事