Pandas实现列表与DataFrame列逐一拼接出错,求正确方法
问题解决:生成租户ID与规则ID的笛卡尔积拼接结果
问题背景
需要将字符串列表tenant_ids中的每个值,与DataFrame的_id列每个值逐一拼接,生成笛卡尔积形式的结果(比如列有20行、列表有5个元素则生成100行)。但现有代码运行后,所有列表值会依次拼接到每个列值上,而非预期的一一对应拼接。
示例数据
- 租户ID列表:
tenant_ids = ["abc", "def", "ghi"] - 原始DataFrame的
_id列:
| _id |
|---|
| Rule_1 |
| Rule_2 |
| Rule_3 |
现有错误代码
tids = [] for t in tenant_ids: day_1_rules['_id'] = t+'-'+day_1_rules['_id'] tids.append(day_1_rules) day_1_rules = pd.concat(tids)
实际错误输出
| _id |
|---|
| abc-def-ghi-Rule_1 |
| abc-def-ghi-Rule_2 |
| abc-def-ghi-Rule_3 |
预期正确输出
| _id |
|---|
| abc-Rule_1 |
| abc-Rule_2 |
| abc-Rule_3 |
| def-Rule_1 |
| def-Rule_2 |
| def-Rule_3 |
| ghi-Rule_1 |
| ghi-Rule_2 |
| ghi-Rule_3 |
错误原因
每次循环直接修改原DataFrame的_id列且未创建副本:第一次循环把_id改成abc-Rule_x,第二次循环会在这个基础上再拼接def-,第三次又叠加ghi-,最终得到多层拼接的结果。同时每次append的都是同一个DataFrame的引用,concat后只是重复了三次已被多次修改的DataFrame,导致结果错误。
正确解法
方法1:循环时创建DataFrame副本
保存原始ID列,每次循环复制原DataFrame并修改副本的_id,最后拼接所有副本:
tids = [] # 保存原始_id列,避免循环中被修改 original_ids = day_1_rules['_id'].copy() for t in tenant_ids: # 创建原DataFrame的独立副本 temp_df = day_1_rules.copy() # 使用原始ID进行拼接,避免重复叠加 temp_df['_id'] = t + '-' + original_ids tids.append(temp_df) # 合并后重置索引 day_1_rules = pd.concat(tids, ignore_index=True)
方法2:交叉合并生成笛卡尔积(高效简洁)
构造租户ID的DataFrame,与原DataFrame做交叉合并后拼接列值:
import pandas as pd # 构造租户ID的DataFrame tenant_df = pd.DataFrame({'tenant_id': tenant_ids}) # 生成笛卡尔积(交叉合并) cross_df = pd.merge(tenant_df, day_1_rules, how='cross') # 拼接成目标_id列 cross_df['_id'] = cross_df['tenant_id'] + '-' + cross_df['_id'] # 保留需要的列并重置索引 day_1_rules = cross_df[['_id']].reset_index(drop=True)
方法3:列表推导式快速生成
直接生成所有拼接后的字符串对,再转为DataFrame:
import pandas as pd # 生成所有拼接组合 all_ids = [f"{t}-{rule}" for t in tenant_ids for rule in day_1_rules['_id'].tolist()] # 转为目标DataFrame day_1_rules = pd.DataFrame({'_id': all_ids})
内容的提问来源于stack exchange,提问作者Will L
相关产品推荐
相关产品推荐

