我有一系列约 350k 行的 pandas,我想使用由约 100 个子字符串组成的正则表达式应用pandas.Series.str.extract函数,例如:
'(item0|item1|item2|item3|item4|item5|item6|item7|item8|item9|item10|item11|item12|item13|item14|item15|item16|item17|item18|item19|item20|item21|item22|item23|item24|item25|item26|item27|item28|item29|item30|item31|item32|item33|item34|item35|item36|item37|item38|item39|item40|item41|item42|item43|item44|item45|item46|item47|item48|item49|item50|item51|item52|item53|item54|item55|item56|item57|item58|item59|item60|item61|item62|item63|item64|item65|item66|item67|item68|item69|item70|item71|item72|item73|item74|item75|item76|item77|item78|item79|item80|item81|item82|item83|item84|item85|item86|item87|item88|item89|item90|item91|item92|item93|item94|item95|item96|item97|item98|item99|item100)'
提取速度太慢:在我的 jupyter notebook(Python 3.9)中需要 1 分钟。为什么这么慢,如何加快速度?
编辑 1我使用“itemX”作为示例,但它可以用任何子字符串替换。正则表达式可以是这样的
'(carrageenan|dihydro|basketball|etc...)'
编辑2回答一些评论:
re.compile()
在处理包含大量行的 Pandas Series 时,使用复杂的正则表达式提取数据确实可能会导致性能问题。以下是一些提高速度的策略:
简化正则表达式:确保正则表达式尽可能高效。避免使用过于复杂的模式。如果你的子字符串之间没有特殊字符,直接用 | 分隔就可以了。
|
使用 str.contains 进行筛选:如果你只是想检查字符串中是否包含某些子字符串,可以先使用 str.contains 来进行筛选,然后再进行提取。这通常会更快。
str.contains
向量化操作:如果可以的话,考虑使用向量化操作,而不是正则表达式提取。可以使用集合或列表推导来检查匹配项。例如:
python items_set = {'carrageenan', 'dihydro', 'basketball', ...} # 你的项 result = your_series.apply(lambda x: next((item for item in items_set if item in x), None))
分块处理:如果数据集非常大,考虑将其分块处理。可以将 Series 拆分为较小的部分,应用正则表达式,然后合并结果。
使用 re.search 或 re.findall:如果你只需要查找匹配而不是提取特定组,可以考虑使用 re.search 或 re.findall,结合 apply(),这在某些情况下可能更快。
re.search
re.findall
apply()
性能分析:使用性能分析工具(如 cProfile)来识别代码中的瓶颈,查看是否有特定的区域可以进一步优化。
cProfile
以下是使用预编译的正则表达式与 apply() 的示例:
import pandas as pd import re # 示例数据 data = pd.Series(["carrageenan is here", "dihydro is here", "nothing here", "basketball game"]) pattern = re.compile(r'(carrageenan|dihydro|basketball)') # 使用 apply 结合正则表达式 result = data.apply(lambda x: pattern.search(x).group(0) if pattern.search(x) else None)
通过这些策略,你应该能够提高处理速度。你可以根据具体情况尝试不同的方法,找到最适合你的数据集的解决方案。