如何使用Pandas加速累积字符串拼接操作?
优化字符串累积序列生成函数的性能
问题背景
需要生成字符串的累积序列:按客户分组,按日期排序后,每个DOCUMENT_CODE对应一条记录,第一条记录的ARTICLE_CODE为0,后续每条记录的ARTICLE_CODE是之前所有文档中ARTICLE_CODE的累积拼接结果。原函数运行速度极慢,尝试NumPy优化无效果。
原函数代码
def create_sequence_shifted(df) -> list: articles = [] customers = df["CUSTOMER"].drop_duplicates() for customer in customers: tmp = df[df["CUSTOMER"]==customer].sort_values(by="DATE").reset_index(drop=True) i=0 for x in tmp["DOCUMENT_CODE"].drop_duplicates(): if i==0: articles += [0] sequence = tmp[tmp["DOCUMENT_CODE"]==x]["PRODUCT_ID"].str.cat(sep =", ") i = 1 else: articles += [sequence] sequence = articles[-1] +", " + tmp[tmp["DOCUMENT_CODE"]==x]["PRODUCT_ID"].str.cat(sep =", ") return articles
初始数据
| CUSTOMER | DATE | DOCUMENT_CODE | ARTICLE_CODE |
|---|---|---|---|
| 1 | 01/01/22 | a | x |
| 1 | 01/01/22 | a | y |
| 1 | 02/01/22 | b | z |
| 1 | 03/01/22 | d | w |
| 2 | 01/01/22 | c | x |
目标转换结果
| CUSTOMER | DATE | DOCUMENT_CODE | ARTICLE_CODE |
|---|---|---|---|
| 1 | 01/01/22 | a | 0 |
| 1 | 02/01/22 | b | x,y |
| 1 | 03/01/22 | d | x,y,z |
| 2 | 01/01/22 | c | 0 |
原代码性能瓶颈
- 嵌套循环遍历客户和文档,时间复杂度随数据量线性增长
- 多次切片DataFrame生成临时对象,内存和计算开销大
- 字符串拼接采用
+=操作,不可变字符串的频繁拼接会产生大量中间对象,效率极低
优化方案(基于Pandas向量化操作)
利用Pandas的分组、聚合和累积操作替代循环,大幅提升效率:
import pandas as pd def create_sequence_optimized(df): # 1. 按客户和日期排序,确保顺序正确 df_sorted = df.sort_values(by=["CUSTOMER", "DATE"]).reset_index(drop=True) # 2. 按客户+文档分组,聚合每个文档的ARTICLE_CODE为逗号分隔字符串 doc_grouped = df_sorted.groupby(["CUSTOMER", "DOCUMENT_CODE", "DATE"])["ARTICLE_CODE"].agg(lambda x: ",".join(x)).reset_index() # 3. 按客户分组,计算累积拼接序列 def cumulate_articles(group): cum_seq = ["0"] if len(group) > 1: docs = group["ARTICLE_CODE"].tolist() for i in range(1, len(group)): cum_seq.append(",".join(docs[:i])) group["ARTICLE_CODE"] = cum_seq return group result = doc_grouped.groupby("CUSTOMER").apply(cumulate_articles).reset_index(drop=True) return result
优化效果说明
- 用
groupby替代嵌套循环,减少重复计算 - 聚合操作一次性处理每个文档的产品拼接,避免多次切片
- 累积拼接时先收集所有文档字符串,再批量生成结果,减少字符串拼接次数
测试验证
将初始数据传入优化后的函数,可直接得到目标结果的DataFrame,无需额外转换列表。
内容的提问来源于stack exchange,提问作者Enrico Grandi
相关产品推荐
相关产品推荐

