Pandas JSON(手把手讲解)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观
前言
在数据分析与编程领域,Pandas JSON 是一个高频出现的关键词。Pandas 作为 Python 生态中处理结构化数据的核心工具,而 JSON(JavaScript Object Notation)因其轻量级、易读性及跨平台兼容性,成为数据交换的首选格式。两者的结合,为开发者提供了高效解析、转换和操作 JSON 数据的能力。无论是从 API 获取实时数据、处理嵌套结构复杂的配置文件,还是将分析结果导出为可共享的 JSON 格式,掌握这一技能链路都能显著提升工作效率。
本文将从基础概念讲起,逐步深入到实际案例与高级技巧,帮助读者系统性掌握 Pandas 处理 JSON 的方法。通过形象化的比喻和可复现的代码示例,即使是编程新手也能快速上手。
一、Pandas 与 JSON 的基础概念
1.1 Pandas 是什么?
Pandas 是 Python 中用于数据操作和分析的库,其核心数据结构是 DataFrame(二维表格)和 Series(一维数组)。它提供了一套高效且灵活的接口,支持数据清洗、聚合、合并等操作,是数据科学家和工程师的必备工具。
1.2 JSON 的结构与特点
JSON 是一种以键值对(Key-Value)存储数据的格式,其结构分为以下层级:
- 标量类型:字符串、数字、布尔值等简单数据。
- 对象(Object):用大括号
{}
包裹的键值对集合,例如:{ "name": "Alice", "age": 30, "is_student": false }
- 数组(Array):用方括号
[]
包裹的多个元素,例如:[10, 20, 30]
- 嵌套结构:对象或数组可以包含其他对象或数组,形成多层结构。
JSON 的优势在于:
- 人类可读性:格式简洁,易于编写和调试。
- 跨语言兼容性:几乎所有编程语言都支持 JSON 解析。
- 轻量级:相比 XML 等格式,JSON 的体积更小。
1.3 Pandas JSON 的核心作用
Pandas 的 json
模块提供了将 JSON 数据转化为 DataFrame 的功能,解决了以下痛点:
- 自动类型推断:将 JSON 的键值对映射为 DataFrame 的列与行。
- 处理嵌套结构:通过参数配置,可展开多层嵌套的 JSON 数据。
- 批量操作能力:利用 Pandas 的向量化操作,快速清洗或转换 JSON 数据。
二、从 JSON 到 DataFrame:基础读取与转换
2.1 直接读取简单 JSON 文件
假设有一个简单的 JSON 文件 data.json
,内容如下:
[
{"id": 1, "name": "Apple", "price": 1.99},
{"id": 2, "name": "Banana", "price": 0.99}
]
使用 pd.read_json()
可直接加载:
import pandas as pd
df = pd.read_json("data.json")
print(df)
id name price
0 1 Apple 1.99
1 2 Banana 0.99
注意:默认读取模式为 orient='columns'
,适用于一维或二维数据。
2.2 处理嵌套 JSON:展开多层结构
当 JSON 数据包含嵌套对象时(例如:每个元素是一个对象,内部有子对象),直接读取会得到 DataFrame 的列类型为 dict
。此时需借助 json_normalize
:
案例:解析用户信息的嵌套 JSON
[
{
"user_id": 101,
"name": "Bob",
"address": {
"city": "New York",
"zip": "10001"
},
"orders": [
{"product": "Laptop", "price": 1000},
{"product": "Mouse", "price": 20}
]
},
{
"user_id": 102,
"name": "Alice",
"address": {
"city": "London",
"zip": "SW1A 1AA"
},
"orders": [
{"product": "Book", "price": 15}
]
}
]
解决方案:使用 pd.json_normalize()
from pandas import json_normalize
import json
json_str = """[...]""" # 省略原始 JSON 内容
data = json.loads(json_str)
df = json_normalize(
data,
record_path=['orders'], # 需要展开的数组字段
meta=[
'user_id',
'name',
['address', 'city'], # 嵌套字段的路径
['address', 'zip']
]
)
print(df)
product price user_id name address.city address.zip
0 Laptop 1000 101 Bob New York 10001
1 Mouse 20 101 Bob New York 10001
2 Book 15 102 Alice London SW1A 1AA
关键参数说明:
record_path
: 指定要展开的数组字段(如orders
)。meta
: 需要保留的顶层字段(如user_id
)或嵌套字段(如address.city
)。- 比喻:将嵌套的 JSON 比作俄罗斯套娃,
json_normalize
就像一把“拆解工具”,一层层展开并平铺到表格中。
2.3 从 API 获取 JSON 数据并解析
实际开发中,常需要从 API 请求 JSON 数据。以下是一个完整流程示例:
案例:调用天气 API 获取数据
import requests
import pandas as pd
response = requests.get("https://api.weatherapi.com/v1/current.json", params={
"key": "YOUR_API_KEY",
"q": "London"
})
data = response.json()
df = pd.json_normalize(data)
print(df)
location.name current.temp_c ...
0 London 15.6 ...
关键步骤:
- 使用
requests
发送请求并获取响应。 - 通过
.json()
方法将响应内容转换为 Python 字典。 - 使用
pd.json_normalize()
将字典结构化为 DataFrame。
三、从 DataFrame 到 JSON:导出与格式控制
3.1 基础导出:to_json()
方法
将 DataFrame 转换为 JSON 格式时,可通过 orient
参数控制输出格式:
示例:导出不同格式的 JSON
df = pd.DataFrame({
"id": [1, 2],
"name": ["Apple", "Banana"],
"price": [1.99, 0.99]
})
print(df.to_json(orient="records", force_ascii=False))
[
{"id":1,"name":"Apple","price":1.99},
{"id":2,"name":"Banana","price":0.99}
]
print(df.to_json(orient="table", force_ascii=False))
{
"schema": {...},
"data": [...]
}
常用 orient
参数:
| 参数值 | 描述 |
|--------------|----------------------------------------|
| records
| 将每一行转换为独立的 JSON 对象(数组形式)。 |
| index
| 以索引为键,列值为值(对象形式)。 |
| columns
| 列名作为键,列数据为值(对象形式)。 |
| split
| 分割为 "index", "columns", "data" 三个部分。 |
3.2 高级导出:自定义嵌套结构
有时需要将 DataFrame 转换为特定嵌套格式,例如:
{
"users": [
{
"id": 101,
"orders": [
{"product": "Laptop", "price": 1000},
{"product": "Mouse", "price": 20}
]
},
...
]
}
实现步骤:
- 分组聚合:按用户 ID 分组,将订单数据转化为列表。
- 自定义转换:通过
apply
或json.dumps
构造嵌套结构。
df = pd.DataFrame({
"user_id": [101, 101, 102],
"product": ["Laptop", "Mouse", "Book"],
"price": [1000, 20, 15]
})
result = df.groupby("user_id").apply(lambda x: x[["product", "price"]].to_dict("records")).reset_index()
result.columns = ["user_id", "orders"]
output = {
"users": result.to_dict("records")
}
print(json.dumps(output, indent=2))
{
"users": [
{
"user_id": 101,
"orders": [
{"product": "Laptop", "price": 1000},
{"product": "Mouse", "price": 20}
]
},
...
]
}
四、进阶技巧与常见场景
4.1 处理动态键:未知或变化的 JSON 字段
当 JSON 数据的键不固定时(例如 API 返回的字段可能随版本变化),可以通过遍历或正则表达式提取关键信息。
案例:提取所有以 "price" 开头的列
df = pd.DataFrame({
"price_1": [10, 20],
"price_2": [5, 8],
"other": ["A", "B"]
})
price_cols = [col for col in df.columns if col.startswith("price")]
price_data = df[price_cols]
print(price_data)
price_1 price_2
0 10 5
1 20 8
4.2 处理缺失值与类型转换
JSON 数据中常存在 null
或类型不一致的情况,需通过 Pandas 的方法进行清洗:
示例:填充缺失值并转换为数值类型
df = pd.DataFrame({
"id": [1, 2, 3],
"value": ["100", "200", None]
})
df["value"] = pd.to_numeric(df["value"], errors="coerce").fillna(0)
print(df)
id value
0 1 100.0
1 2 200.0
2 3 0.0
4.3 性能优化:处理大型 JSON 文件
对于超大规模的 JSON 文件(如 GB 级),直接读取可能因内存不足而崩溃。此时可采用以下策略:
方法 1:分块读取(Chunk Processing)
chunk_size = 1000
for chunk in pd.read_json("large_data.json", lines=True, chunksize=chunk_size):
# 处理每个小块数据
process(chunk)
方法 2:使用第三方库(如 ijson
)
ijson
库支持流式解析,避免一次性加载全部数据:
import ijson
with open("large_data.json", "r") as f:
parser = ijson.parse(f)
for prefix, event, value in parser:
if (prefix, event) == ("item", "start_map"):
# 处理每个 JSON 对象
process_item(value)
五、常见问题与解决方案
5.1 问题:JSON 数据读取后出现 Mixed Types
警告
现象:Pandas 提示列内数据类型不一致,例如字符串与数字混合。
原因:JSON 中某些字段可能包含 null
或非预期类型。
解决方案:
df = pd.read_json("data.json", dtype={"price": float})
df["price"].fillna(0, inplace=True)
5.2 问题:嵌套层级过深导致 json_normalize
失败
现象:多层嵌套的 JSON 无法通过 json_normalize
完全展开。
解决方案:
- 分步展开:先展开部分层级,再对子结构递归处理。
- 自定义函数:编写辅助函数逐层解析复杂结构。
def recursive_flatten(d, parent_key="", sep="_"):
items = []
for k, v in d.items():
new_key = f"{parent_key}{sep}{k}" if parent_key else k
if isinstance(v, dict):
items.extend(recursive_flatten(v, new_key, sep).items())
else:
items.append((new_key, v))
return dict(items)
df = df.applymap(lambda x: recursive_flatten(x) if isinstance(x, dict) else x)
六、结论与展望
通过本文的讲解,读者应能掌握 Pandas JSON 的核心操作:从读取简单数据到处理复杂嵌套结构,从数据清洗到导出定制化格式。关键要点总结如下:
- 基础工具链:
pd.read_json
和pd.json_normalize
是处理 JSON 的核心函数。 - 嵌套处理:通过
record_path
和meta
参数实现多层展开。 - 性能优化:分块读取或流式解析可应对大规模数据。
未来,随着数据工程的复杂化,熟练使用 Pandas 处理 JSON 将成为开发者必备技能。建议读者结合实际项目继续探索,例如:
- 将 JSON 数据与数据库操作结合(如导出到 SQL)。
- 结合可视化库(如 Plotly)直接从 JSON 数据生成图表。
- 学习更复杂的 JSON Schema 验证与数据转换逻辑。
掌握 Pandas JSON,不仅能提升个人技术竞争力,更能为构建高效的数据处理流程打下坚实基础。