Polars字符串列高效过滤:内存优化与纯表达式实现咨询
处理大文本列的Polars性能与内存问题
问题背景
我有一列长字符串(如语句),需完成以下处理:
- 替换特定字符;
- 拆分剩余字符串为列表;
- 纯文本字符串若在字典中则保留;
- 纯数字字符串保留;
- 混合字符串按数字与字母比率筛选。
当前实现方式:遍历目标列,使用Polars的map_elements调用Python自定义函数filter_field完成处理,该函数通过正则替换、拆分字符串、计算字符比率等逻辑实现过滤。
- 处理128M行数据耗时约10分钟;
- 处理300M行时内存持续增长直至被Ubuntu系统终止,且仅单核心运行。
核心问题
- 原方案内存增长是否正常?
map_elements是否会复制原序列导致内存消耗增加? - 原方案是否合理,有无更优实现方式(如使用Polars的struct)?
- 能否仅通过Polars表达式完成上述所有过滤逻辑?
额外问题
尝试使用Polars表达式后性能大幅提升,但存在两个问题:
- 字典查询复杂度严重影响运行效率;
- 使用
pl.DataFrame保存为parquet格式时出现段错误,改用pl.LazyFrame+sink_parquet无错误但耗时显著增加。
示例数据
temp = pl.DataFrame({"foo": ['COOOPS.autom.SAPF124', 'OSS REEE PAAA comp. BEEE atm 6079 19000000070 04-04-2023', 'ABCD 600000000397/7667896-6/REG.REF.REE PREPREO/HMO', 'OSS REFF pagopago cost. Becf atm 9682 50012345726 10-04-2023'] })
自定义函数代码
def num_dec(x): return len(re.findall(r'[0-9_\/]', x)) def num_letter(x): return len(re.findall(r'[A-Za-z]', x)) def letter_dec_ratio(x): if len(x) == 0: return None nl = num_letter(x) nd = num_dec(x) if (nl + nd) == 0: return None ratio = (nl - nd)/(nl + nd) return ratio def filter_field(text=None, word_dict=None): if type(text) is not str or word_dict is None: return 'no memo and/or dictionary' if len(text) > 100: text = text[0:101] print("TEXT: ",text) text_sani = re.sub(r'[^a-zA-Z0-9\s\_\-\%]', ' ', text) # parse by replacing most artifacts and symbols with space words = text_sani.split(' ') # create words separated by spaces print("WORDS: ",words) kept = [] ratios = [letter_dec_ratio(w) for w in words] [kept.append(w.lower()) for i, w in enumerate(words) if ratios[i] is not None and ((ratios[i] == -1 or (-0.7 <= ratios[i] <= 0)) or (ratios[i] == 1 and w.lower() in word_dict))] print("FINAL: ",' '.join(kept)) return ' '.join(kept)
当前实现代码
temp.with_columns( pl.col("foo").map_elements( lambda x: filter_field(text=x, word_dict=['cost','atm'])).alias('clean_foo') # baseline )
Polars表达式部分尝试代码
temp.with_columns( ( pl.col(col) .str.replace_all(r'[^a-zA-Z0-9\s\_\-\%]',' ') .str.split(' ') ) )
预期结果
TEXT: COOOPS.autom.SAPF124 WORDS: ['COOOPS', 'autom', 'SAPF124'] FINAL: TEXT: OSS REEE PAAA comp. BEEE atm 6079 19000000070 04-04-2023 WORDS: ['OSS', 'REEE', 'PAAA', 'comp', '', 'BEEE', '', 'atm', '6079', '19000000070', '04-04-2023'] FINAL: atm 6079 19000000070 04-04-2023 TEXT: ABCD 600000000397/7667896-6/REG.REF.REE PREPREO/HMO WORDS: ['ABCD', '600000000397', '7667896-6', 'REG', 'REF', 'REE', 'PREPREO', 'HMO'] FINAL: 600000000397 7667896-6 TEXT: OSS REFF pagopago cost. Becf atm 9682 50012345726 10-04-2023 WORDS: ['OSS', 'REFF', 'pagopago', 'cost', '', 'Becf', '', 'atm', '9682', '50012345726', '10-04-2023'] FINAL: cost atm 9682 50012345726 10-04-2023
内容的提问来源于stack exchange,提问作者MikeB2019x
相关产品推荐
相关产品推荐

