56_Pandas读取 JSON 字符串/文件 (read_json)
使用pandas.read_json()函数,可以将JSON格式字符串(str类型)和文件读取为pandas.DataFrame。它还支持 JSON 行 (.jsonl)。
读取成pandas.DataFrame后,可以做各种数据分析,也可以用to_csv()方法保存成csv文件,这样就可以很方便的通过pandas将JSON文件转为CSV文件。
在此,对以下内容进行说明。
- pandas.read_json() 的基本用法
- 读取 JSON 格式字符串
- 读取JSON格式文件
- 读取压缩文件:参数compression
- 指定格式:参数orient
- 读取 JSON 行 (.jsonl)
- 读取 JSON 字符串/文件的一部分
pandas.read_json() 的基本用法
用作示例的字符串和文件是在以下文章中创建的。
读取 JSON 格式字符串
如果将 JSON 格式的字符串传递给 pandas.read_json() 函数的第一个参数,该字符串将被转换为 pandas.DataFrame。
import pandas as pd
import json
s = '{"col1":{"row1":1,"row2":2,"row3":3},"col2":{"row1":"a","row2":"x","row3":"\u554a"}}'
df_s = pd.read_json(s)
print(df_s)
# col1 col2
# row1 1 a
# row2 2 x
# row3 3 啊
将原始字符串中的 Unicode 转义序列 \uXXXX 转换为相应的字符。 注意JSON字符串中的引号必须是双引号"。单引号’会导致错误(ValueError)。
s_single_quote = "{'col1':{'row1':1,'row2':2,'row3':3},'col2':{'row1':'a','row2':'x','row3':'\u554a'}}"
# df_s_single_quote = pd.read_json(s_single_quote)
# ValueError: Expected object or value
对于使用单引号 ’ 的字符串,使用字符串方法 replace() 将单引号 ’ 替换为双引号 "。
print(pd.read_json(s_single_quote.replace("'", '"')))
# col1 col2
# row1 1 a
# row2 2 x
# row3 3 啊
读取JSON格式文件
如果将 JSON 格式文件路径传递给 pandas.read_json() 函数的第一个参数,该文件将被读取为 pandas.DataFrame。
df_f = pd.read_json('data/sample_from_pandas_columns.json')
print(df_f)
# col1 col2
# row1 1 a
# row2 2 x
# row3 3 啊
读取压缩文件:参数compression
pandas 0.21.0版本加入了参数compression,指定’gzip’, ‘bz2’, ‘zip’, 'xz’可以直接读取压缩文件。
如果扩展名是.gz、.bz2、.zip、.xz,设置compression='infer’会自动选择对应的压缩方式。
df_gzip = pd.read_json('data/sample_from_pandas_columns.gz', compression='infer')
print(df_gzip)
# col1 col2
# row1 1 a
# row2 2 x
# row3 3 啊
请注意,这仅适用于压缩的单个文件,无法读取包含多个文件的 zip。
指定格式:参数orient
pandas.DataFrame的行标签index、column标签column、value值如何赋值JSON的内容有以下几种格式。
- ‘split’
- {index -> [index], columns -> [columns], data -> [values]}
- ‘records’
- [{column -> value}, … , {column -> value}]
- ‘index’
- {index -> {column -> value}}
- ‘columns’(default)
- {column -> {index -> value}}
- ‘values’
- [values]
有关实际示例,请参阅下面的文章。
注意,如果要读取的字符串或文件的格式与orient参数中指定的格式不同,会导致行列互换或出错。
df_s_index = pd.read_json(s, orient='index')
print(df_s_index)
# row1 row2 row3
# col1 1 2 3
# col2 a x 啊
# df_s_split = pd.read_json(s, orient='split')
# ValueError: JSON data had unexpected key(s): col2, col1
读取 JSON 行 (.jsonl)
JSON 行 (.jsonl) 是用换行符分隔的 JSON。
如果参数 orient=‘records’ 和参数 lines=True,您可以使用 pandas.read_json() 读取 JSON 行 (.jsonl)。
s_jsonl = '''{"col1":1,"col2":"a"}
{"col1":2,"col2":"x"}
{"col1":3,"col2":"\u554a"}'''
print(s_jsonl)
# {"col1":1,"col2":"a"}
# {"col1":2,"col2":"x"}
# {"col1":3,"col2":"啊"}
df_s_jsonl = pd.read_json(s_jsonl, orient='records', lines=True)
print(df_s_jsonl)
# col1 col2
# 0 1 a
# 1 2 x
# 2 3 啊
要读取 JSONL 文件,只需在第一个参数中指定文件路径,如上例所示。
读取 JSON 字符串/文件的一部分
事实上,可以通过Web API等获取的JSON除了作为pandas.DataFrame读取的数据之外还有其他信息,因此在很多情况下不能直接应用pandas.read_json()。
在这种情况下,可以按以下流程阅读。可能有更好的方法。
1.使用标准库json模块的json.loads()和json.load()将JSON字符串和文件作为
2.字典读取 从字典中提取你想读的部分
3.使用 json.dumps() 将提取的部分转换为字符串
4.将字符串传递给 pandas.read_json()
以下面的嵌套 JSON 字符串为例。
s_nested = '{"OTHER": "x", "DATA": {"col1":{"row1":1,"row2":2},"col2":{"row1":"a","row2":"x"}}}'
如果按原样传递给 pandas.read_json() ,它将如下所示。
print(pd.read_json(s_nested))
# DATA OTHER
# col1 {'row1': 1, 'row2': 2} x
# col2 {'row1': 'a', 'row2': 'x'} x
首先,使用 json.loads() 将其转换为字典。 json.load() 加载文件。
d = json.loads(s_nested)
print(d)
# {'OTHER': 'x', 'DATA': {'col1': {'row1': 1, 'row2': 2}, 'col2': {'row1': 'a', 'row2': 'x'}}}
print(type(d))
# <class 'dict'>
从字典中提取要读取的部分作为 pandas.DataFrame。如果嵌套很深,则重复 [key name] [key name]。
d_target = d['DATA']
print(d_target)
# {'col1': {'row1': 1, 'row2': 2}, 'col2': {'row1': 'a', 'row2': 'x'}}
print(type(d_target))
# <class 'dict'>
使用 json.dumps() 转换为字符串。
s_target = json.dumps(d_target)
print(s_target)
# {"col1": {"row1": 1, "row2": 2}, "col2": {"row1": "a", "row2": "x"}}
print(type(s_target))
# <class 'str'>
传递给 pandas.read_json()。根据格式指定参数方向。示例默认值(orient=‘columns’)。
df_target = pd.read_json(s_target)
print(df_target)
# col1 col2
# row1 1 a
# row2 2 x
一起写也OK了。
df_target2 = pd.read_json(json.dumps(json.loads(s_nested)['DATA']))
print(df_target2)
# col1 col2
# row1 1 a
# row2 2 x
如果你要阅读的部分是orient=‘records’(字典列表)格式,你可以使用pandas.io.json.json_normalize()将字典列表直接转换为pandas.DataFrame。