其实前面学的根本不记得了,小丑.jpg,如果真的面试问到了估计也是一脸懵
今日任务:
JSON
先认识一下JSON和JSONL文件
记得之前在面试KIMI的时候,面试官就给我出了JSONL和EXCEL转换的手撕代码题,而那个时候,我连什么是JSONL都不知道,然后毫无疑问的挂了。
JSON文件
使用大括号 {} 表示对象,使用方括号 [] 表示数组,用来将所有的对象包装在一起。
整个文件是一个有效的 JSON 对象或数组。
适合存储结构化的数据,如配置文件、API 响应等。
一次性读取整个文件,解析成一个 JSON 对象,可以随机访问其中的数据。
{
"class": "Year 1",
"student" :[
{"name": "John", "age": 30},
{"name": "Jane", "age": 25},
{"name": "Bob", "age": 40}
]}
JSONL文件
每行是一个独立的有效 JSON 对象。
每行之间没有逗号或其他分隔符。
适合存储每行为独立记录的数据,如日志、传感器数据、日志行等。
逐行读取文件,逐行解析 JSON 对象,一次处理一行的数据。
{"name": "John", "age": 30}
{"name": "Jane", "age": 25}
{"name": "Bob", "age": 40}
从JSON文件加载数据
read_json() 用于从 JSON 格式的数据中读取并加载为一个 DataFrame。它支持从 JSON 文件、JSON 字符串或 JSON 网址中加载数据。
import pandas as pddf = pd.read_json(path_or_buffer, # JSON 文件路径、JSON 字符串或 URLorient=None, # JSON 数据的结构方式,默认是 'columns',会根据文件自动判断dtype=None, # 强制指定列的数据类型convert_axes=True, # 是否转换行列索引convert_dates=True, # 是否将日期解析为日期类型keep_default_na=True # 是否保留默认的缺失值标记
)
常见的 orient 参数选项:
orient 值 | JSON 格式示例 | 描述 |
---|---|---|
split | {"index":["a","b"],"columns":["A","B"],"data":[[1,2],[3,4]]} | 使用键 index 、columns 和 data 结构 |
records | [{"A":1,"B":2},{"A":3,"B":4}] | 每个记录是一个字典,表示一行数据 |
index | {"a":{"A":1,"B":2},"b":{"A":3,"B":4}} | 使用索引为键,值为字典的方式 |
columns | {"A":{"a":1,"b":3},"B":{"a":2,"b":4}} | 使用列名为键,值为字典的方式 |
values | [[1,2],[3,4]] | 只返回数据,不包括索引和列名 |
从URL中读取JSON数据
import pandas as pdURL = 'https://static.jyshare.com/download/sites.json'
df = pd.read_json(URL)
print(df)
JSON字符串
import pandas as pd# JSON 字符串
json_data = '''
[{"Name": "Alice", "Age": 25, "City": "New York"},{"Name": "Bob", "Age": 30, "City": "Los Angeles"},{"Name": "Charlie", "Age": 35, "City": "Chicago"}
]
'''# 从 JSON 字符串读取数据
df = pd.read_json(json_data)print(df)#如果是下面这样
json_data = [{"Name": "Alice", "Age": 25, "City": "New York"},{"Name": "Bob", "Age": 30, "City": "Los Angeles"},{"Name": "Charlie", "Age": 35, "City": "Chicago"}
]#用df = pd.read_json(json_data)就会报错
df = pd.DataFrame(json_data)
如果JSON内容很多,直接print(df)可能会打印不全,用print(df.to_srting())会打印完整数据
JSON数据内嵌
假设JSON数据中包含列表
# nested_list.json
{"school_name": "ABC primary school","class": "Year 1","students": [{"id": "A001","name": "Tom","math": 60,"physics": 66,"chemistry": 61},{"id": "A002","name": "James","math": 89,"physics": 76,"chemistry": 51},{"id": "A003","name": "Jenny","math": 79,"physics": 90,"chemistry": 78}]
}
如果直接read_json
import pandas as pddf = pd.read_json('nested_list.json')print(df)
结果是
school_name class students
0 ABC primary school Year 1 {'id': 'A001', 'name': 'Tom', 'math': 60, 'phy...
1 ABC primary school Year 1 {'id': 'A002', 'name': 'James', 'math': 89, 'p...
2 ABC primary school Year 1 {'id': 'A003', 'name': 'Jenny', 'math': 79, 'p...
如果我们想把students的数据转换成DataFrame,可以使用json_normalize()将折叠的JSON数据展平。record_path用于提取深层嵌套的列表,如果students列表嵌套在info这个字典中,则record_path可以写成,下文的meta参数同理。
record_path=['info', 'students'] # 多层路径用列表表示:先找 info,再找 students
import pandas as pd
import json# 使用 Python JSON 模块载入数据
with open('nested_list.json','r') as f:data = json.loads(f.read())# 展平数据
df_nested_list = pd.json_normalize(data, record_path =['students'])
print(df_nested_list)
结果就是:
id name math physics chemistry
0 A001 Tom 60 66 61
1 A002 James 89 76 51
2 A003 Jenny 79 90 78
如果要将school_name 和 class 也作为列,则使用'meta'参数
import pandas as pd
import json# 使用 Python JSON 模块载入数据
with open('nested_list.json','r') as f:data = json.loads(f.read())# 展平数据
df_nested_list = pd.json_normalize(data, record_path =['students'], meta=['school_name', 'class']
)
print(df_nested_list)
可以看到school_name 和 class添加到了最后两列,且三行数据是一样的
id name math physics chemistry school_name class
0 A001 Tom 60 66 61 ABC primary school Year 1
1 A002 James 89 76 51 ABC primary school Year 1
2 A003 Jenny 79 90 78 ABC primary school Year 1
如果JSON文件中既包含列表,又包含字典,如
{"school_name": "local primary school","class": "Year 1","info": {"president": "John Kasich","address": "ABC road, London, UK","contacts": {"email": "admin@e.com","tel": "123456789"}},"students": [{"id": "A001","name": "Tom","math": 60,"physics": 66,"chemistry": 61},{"id": "A002","name": "James","math": 89,"physics": 76,"chemistry": 51},{"id": "A003","name": "Jenny","math": 79,"physics": 90,"chemistry": 78}]
}
现在将students和info.president和info.contats.tel构成dataframe
import pandas as pd
import json# 使用 Python JSON 模块载入数据
with open('nested_mix.json','r') as f:data = json.loads(f.read())df = pd.json_normalize(data, record_path =['students'], meta=['class',['info', 'president'], #表示先找info,再找president['info', 'contacts', 'tel']#表示先找info,再找contacts,再找tel]
)print(df)
输出就是
id name math physics chemistry class info.president info.contacts.tel
0 A001 Tom 60 66 61 Year 1 John Kasich 123456789
1 A002 James 89 76 51 Year 1 John Kasich 123456789
2 A003 Jenny 79 90 78 Year 1 John Kasich 123456789
其他更复杂嵌套,用到glom模块,建议直接问AI吧
不用 record_path的一个小实验
nested_list.json
{"class": "一班","students": [{"name": "张三", "age": 18},{"name": "李四", "age": 19}]
}test.py
import pandas as pd
import json# 先使用json模块读取文件
with open('nested_list.json', 'r') as f:data = json.load(f)
df = pd.json_normalize(data)
print(df['students'])
会输出
0 [{'name': '张三', 'age': 18}, {'name': '李四', 'age': 19}]
Name: students, dtype: object
因为JSON结构是顶层字典包含students键,所以会直接将顶层键students解析为一列,而students键是一个列表,所以students对应的值就是整个列表
df['class']
对应的值是字符串"一班"
df['students']
对应的值是整个学生列表(未被进一步展开,因为它本身就是顶层键)
如果不用json.load,直接pd.read_json('nested_list.json'),则会报错,因为'nested_list.json'里含有复杂嵌套,无法解析为dataframe
输出为JSON文件
DataFrame.to_json() - 将 DataFrame 转换为 JSON 数据,并指定JSON的结构化方式
df.to_json(path_or_buffer=None, # 输出的文件路径或文件对象,如果是 None 则返回 JSON 字符串orient=None, # JSON 格式方式,支持 'split', 'records', 'index', 'columns', 'values'date_format=None, # 日期格式,支持 'epoch', 'iso'default_handler=None, # 自定义非标准类型的处理函数lines=False, # 是否将每行数据作为一行(适用于 'records' 或 'split')encoding='utf-8' # 编码格式
)
默认用columns格式转换JSON
import pandas as pd# 创建 DataFrame
df = pd.DataFrame({'Name': ['Alice', 'Bob', 'Charlie'],'Age': [25, 30, 35],'City': ['New York', 'Los Angeles', 'Chicago']
})#路径为空,则不会生成JSON文件,返回 JSON 字符串
json_str = df.to_json()print(json_str)'''
{"Name":{"0":"Alice","1":"Bob","2":"Charlie"},"Age":{"0":25,"1":30,"2":35},"City":{"0":"New York","1":"Los Angeles","2":"Chicago"}}
'''
用records模式审
import pandas as pd# 创建 DataFrame
df = pd.DataFrame({'Name': ['Alice', 'Bob', 'Charlie'],'Age': [25, 30, 35],'City': ['New York', 'Los Angeles', 'Chicago']
})# 将 DataFrame 转换为 JSON 文件,指定 orient='records'
#路径不为空
df.to_json('data.json', orient='records', lines=True)'''
{"Name":"Alice","Age":25,"City":"New York"},
{"Name":"Bob","Age":30,"City":"Los Angeles"},
{"Name":"Charlie","Age":35,"City":"Chicago"}
'''
JSON稍微有点复杂,主要是嵌套