Pandas DataFrame分组后拼接行列值至新列:优化低效代码
如何高效在Pandas分组后拼接行列值生成指定格式列
问题背景
需求是按指定列分组后,将每组第一行的列值作为键,后续行的对应列值作为值,拼接成key=value;key2=value2格式的字符串赋值给新列structure_data。现有代码能实现功能,但因大量使用循环和逐行apply操作,运行效率极低。
优化思路
原代码性能瓶颈在于逐列循环拼接字符串和逐行调用apply处理数值,这两类操作在Pandas中属于低效操作。优化核心是利用Pandas的向量化特性,批量处理分组内的键值对拼接逻辑,减少循环和逐行操作。
高效实现代码
方案一:分组内批量处理
import pandas as pd def try_round(x): # 根据实际需求实现数值处理逻辑,示例为保留5位小数 return round(x, 5) if isinstance(x, float) else x # 按指定列分组 groups = df.groupby("row_number") def process_group(group): # 提取分组内第一行的键值(如0D、1D) keys = group.iloc[0, 1:-1].tolist() # 跳过第一列和最后一列structure_data # 筛选分组内的数据行(跳过第一行表头行) data_rows = group.iloc[1:] # 批量处理数值列:先格式化数值,再转字符串 formatted_cols = data_rows.iloc[:, 1:-1].applymap(try_round).astype(str) # 每行生成拼接后的目标字符串 formatted_cols["structure_data"] = formatted_cols.apply( lambda row: ";".join(f"{k}={v}" for k, v in zip(keys, row)), axis=1 ) # 合并回原数据的其他列 result = pd.concat([data_rows.iloc[:, [0]], formatted_cols], axis=1) return result # 合并所有分组的处理结果 df_new = pd.concat([process_group(g) for _, g in groups], ignore_index=True)
方案二:全局批量映射(超大数据量推荐)
通过全局提取分组键并映射,进一步减少分组内的重复操作,数据量越大性能提升越明显:
# 提取每个分组对应的键列表,转为字典映射 group_keys = groups.apply(lambda g: g.iloc[0, 1:-1].tolist()).to_dict() # 筛选所有数据行(跳过每组的第一行表头行) data_df = df[df.groupby("row_number").cumcount() > 0].copy() # 为每个数据行匹配对应的分组键 data_df["_temp_keys"] = data_df["row_number"].map(group_keys) # 批量格式化数值列 formatted_cols = data_df.iloc[:, 1:-2].applymap(try_round).astype(str) # 生成目标字符串 data_df["structure_data"] = data_df.apply( lambda row: ";".join(f"{k}={v}" for k, v in zip(row["_temp_keys"], formatted_cols.loc[row.name])), axis=1 ) # 清理临时列,得到最终结果 df_new = data_df.drop("_temp_keys", axis=1)
优化效果说明
- 用
applymap代替逐行apply处理数值,利用向量化操作大幅提升处理速度; - 避免逐列循环拼接字符串,改为一次性生成所有键值对再合并,减少中间对象的创建开销;
- 方案二通过全局映射逻辑,将分组内的重复操作前置,进一步降低计算复杂度。
内容的提问来源于stack exchange,提问作者Samboo
相关产品推荐
相关产品推荐

