如何使用Python pandas按URL列值将多行数据合并为单行
同URL多记录横向拼接实现方案
核心逻辑
你的场景用pandas原生能力就能实现,不需要额外依赖小众第三方库。由于原始数据中相同URL对应的Date、Description取值完全一致,仅Category存在差异,核心处理流程为按URL分组后,将组内多条记录的字段横向展开,最终列数会自动适配单个URL对应的最大记录数。
基础场景实现代码
先构造和你描述结构一致的测试数据,可直接运行验证效果:
import pandas as pd # 示例原始数据 df = pd.DataFrame({ "Date": ["2024-01-01", "2024-01-01", "2024-01-01", "2024-01-02", "2024-01-02"], "URL": ["url1", "url1", "url1", "url2", "url2"], "Description": ["page1", "page1", "page1", "page2", "page2"], "Category": ["A", "B", "C", "A", "B"] }) # 按URL分组,固定字段取组内第一个值即可,收集所有Category为有序列表 grouped_res = df.groupby("URL", as_index=False).agg( Date=("Date", "first"), Description=("Description", "first"), Category_collect=("Category", list) ) # 将收集到的Category列表拆分为独立列 category_cols = pd.DataFrame(grouped_res["Category_collect"].tolist(), index=grouped_res.index) category_cols.columns = [f"Category_{i+1}" for i in category_cols.columns] # 拼接得到最终结果 final_df = pd.concat([grouped_res[["URL", "Date", "Description"]], category_cols], axis=1)
运行后url1对应1行,后面带3个Category列;url2对应1行,后面带2个Category列,无对应值的位置自动填充空值,符合列数动态扩展的要求。
通用场景适配
如果后续数据不再满足「同URL下Date、Description完全一致」的前提,需要把每条记录的所有字段都按顺序横向排列,可以用全字段拆列的版本:
# 按URL分组收集所有字段的取值列表 grouped_res = df.groupby("URL", as_index=False).agg(list) # 计算单个URL对应的最大记录数,确定最终展开的总列数 max_record_num = grouped_res["Date"].map(len).max() expanded_list = [] # 逐字段拆分为多列 for field in ["Date", "Description", "Category"]: field_split = pd.DataFrame(grouped_res[field].tolist(), index=grouped_res.index) field_split.columns = [f"{field}_{i+1}" for i in range(max_record_num)] expanded_list.append(field_split) # 拼接得到最终宽表 final_df = pd.concat([grouped_res[["URL"]]] + expanded_list, axis=1)
这个版本输出的结果会按顺序排列每个URL下第1条记录的Date、Description、Category,第2条记录的对应字段,直到覆盖该URL下的所有记录,完全匹配你描述的目标效果。
大数据量优化方案
如果你的数据集规模在千万级以上,pandas处理内存占用较高,可以替换为polars库实现相同逻辑,语法和pandas接近,运行速度和内存表现比pandas高3~10倍;常规十万到百万级规模的数据集用pandas即可,不需要额外安装依赖。
内容的提问来源于stack exchange,提问作者Nahuel Mel
相关产品推荐
相关产品推荐

