加速Pandas DataFrame中literal_eval的apply操作方案咨询
Pandas技术栈内优化大规模DataFrame解析与展开的方案
问题场景
你有包含id、value、somedate列的DataFrame,value列是字符串形式的列表,原处理代码在小数据集可行,但数千万至数亿行的大型数据下速度极慢:
数据示例:
id | value | somedate ------------------------------ 1 | [10, 13, 14] | 2024-06-01 2 | [5, 6, 7] | 2024-07-01 3 | [1, 2, 3] | 2024-06-01
原处理代码:
import ast import pandas as pd data = pd.DataFrame({"id": [1, 2, 3], "value": ["[10, 13, 14]", "[5, 6, 7]", "[1, 2, 3]"], "somedate": ["2024-06-01", "2024-07-01", "2024-06-01"]}) data["parsed_value"] = data["value"].apply(lambda x: ast.literal_eval(x)) data = data.explode(column="parsed_value")
以下是Pandas技术栈内的优化方案:
方案一:使用
pd.eval批量解析pd.eval是矢量化操作,相比逐行调用ast.literal_eval效率提升显著,适合批量解析字符串形式的列表:import pandas as pd data = pd.DataFrame({"id": [1, 2, 3], "value": ["[10, 13, 14]", "[5, 6, 7]", "[1, 2, 3]"], "somedate": ["2024-06-01", "2024-07-01", "2024-06-01"]}) # 批量解析整个value列 data["parsed_value"] = pd.eval(data["value"].tolist()) data = data.explode("parsed_value")方案二:字符串原生处理(格式规整场景)
若value列的字符串格式完全统一(仅包含数字、逗号、方括号),可直接用字符串分割替代解析,速度比pd.eval更快,但容错性较低:import pandas as pd data = pd.DataFrame({"id": [1, 2, 3], "value": ["[10, 13, 14]", "[5, 6, 7]", "[1, 2, 3]"], "somedate": ["2024-06-01", "2024-07-01", "2024-06-01"]}) # 去除首尾方括号后按逗号分割为列表 data["parsed_value"] = data["value"].str.strip("[]").str.split(",", expand=False) # 转换为整数类型(按需执行) data["parsed_value"] = data["parsed_value"].apply(lambda x: [int(num.strip()) for num in x]) data = data.explode("parsed_value")方案三:用
swifter自动优化applyswifter库会自动判断当前操作适合矢量化还是并行处理,无需手动编写并行逻辑,能在保留ast.literal_eval容错性的同时提升速度:
先安装依赖:pip install swifterimport ast import pandas as pd import swifter data = pd.DataFrame({"id": [1, 2, 3], "value": ["[10, 13, 14]", "[5, 6, 7]", "[1, 2, 3]"], "somedate": ["2024-06-01", "2024-07-01", "2024-06-01"]}) # 自动优化的apply操作 data["parsed_value"] = data["value"].swifter.apply(ast.literal_eval) data = data.explode("parsed_value")方案四:读取阶段直接解析
如果数据来自外部文件(如CSV),可在读取时通过converters参数直接解析value列,避免后续二次处理,减少内存占用:import ast import pandas as pd # 读取CSV时直接解析value列 data = pd.read_csv("your_large_data.csv", converters={"value": ast.literal_eval}) # 直接展开原value列并重命名 data = data.explode("value").rename(columns={"value": "parsed_value"})
内容的提问来源于stack exchange,提问作者abudis
相关产品推荐
相关产品推荐

