pandas读取大型JSON书评文件内存错误及分块读取报错解决
报错原因
这个报错和你的JSON文件结构没有关系,纯粹是条件判断写法错误:chunk[chunk['overall'] > 3]返回的是按条件过滤后的DataFrame子集,本身不是布尔值,直接放在if后面做真值判断,就会触发pandas的真值歧义报错。
另外你原来的代码还有两个明显的效率问题:
chunksize=1等于逐行读取,大文件下IO和解析开销极高,运行速度会非常慢- 没有跳过评分=3的中性评论,也没做样本量的截断控制,很容易采集超量或者把无效数据加入结果集
正确实现代码
先初始化两个存储列表,设置合理的块大小平衡内存占用和读取速度,修正条件判断逻辑,在正负样本都采集够25万条时立刻终止读取,避免多余的性能消耗:
import pandas as pd # 初始化样本存储列表 pos_revs = [] neg_revs = [] # 目标单类样本采集量 TARGET_NUM = 250000 # 合理设置块大小,不要设为1,内存足够可以适当调大到50000~100000提升速度 CHUNK_SIZE = 10000 with pd.read_json( 'path/Books_5.json', lines=True, chunksize=CHUNK_SIZE, # 只读取需要的两列,大幅降低内存占用,避免内存溢出 usecols=['overall', 'reviewText'] ) as reader: for chunk in reader: # 先过滤掉评分=3的中性评论 chunk = chunk[chunk['overall'] != 3] # 处理正样本(4、5分) pos_chunk = chunk[chunk['overall'] > 3]['reviewText'].tolist() pos_need = TARGET_NUM - len(pos_revs) if pos_need > 0 and len(pos_chunk) > 0: pos_revs.extend(pos_chunk[:pos_need]) # 处理负样本(1、2分) neg_chunk = chunk[chunk['overall'] < 3]['reviewText'].tolist() neg_need = TARGET_NUM - len(neg_revs) if neg_need > 0 and len(neg_chunk) > 0: neg_revs.extend(neg_chunk[:neg_need]) # 两类样本都采集达标就直接退出循环 if len(pos_revs) >= TARGET_NUM and len(neg_revs) >= TARGET_NUM: break # 后续可以直接拼接为可用的情感分析数据集 final_dataset = pd.DataFrame({ 'reviewText': pos_revs + neg_revs, 'sentiment': [1]*len(pos_revs) + [0]*len(neg_revs) })
补充说明
- 代码中添加的
usecols参数只加载任务必需的两个字段,相比加载全字段能降低60%以上的内存占用,从根源上避免大文件读取的内存溢出问题 - 每块处理时自动计算当前还需要补充的样本量,不会出现采集数量超过25万的问题
- 读取逻辑完全适配每行一个JSON对象的行式JSON结构,不需要额外做格式解析调整
内容的提问来源于stack exchange,提问作者AhmedKamal2021
相关产品推荐
相关产品推荐

