如何在Pandas中获取两列值的双向组合对?
实现DataFrame的Source-Target双向配对
我明白你想要实现的是让DataFrame里的每个Source-Target配对都有双向记录——既有A→B,也有B→A,不管原数据里是否已经存在反向行。之前尝试的groupby方法确实不适用,因为它主要用于聚合统计,而非重排或补充行。下面给你两种解决方案,对应不同的需求场景:
场景1:基于现有行生成反向行(交换对应列)
如果你的需求是为每一行生成对应的反向行,交换Source和Target,同时交换Source location和Target location,Value可以复用原行值或自定义修改,那么可以用以下步骤:
代码实现
import pandas as pd # 你的原始DataFrame df = pd.DataFrame({ 'Source': ['a', 'c', 'c', 'p', 'x'], 'Target': ['b', 'v', 'd', 'q', 'z'], 'Value': [10, 10, 18, 10, 8], 'Source location': [[12.3,1.9], [15.3,1.9], [1.4,31.9], [12.3,1.9], [6.3,1.4]], 'Target location': [[13.5,14.3], [13.5,94.3], [16.6,44.7], [13.5,15.3], [47.5,4.3]] }) # 生成反向行的DataFrame reverse_df = df.copy() # 交换Source和Target列 reverse_df[['Source', 'Target']] = reverse_df[['Target', 'Source']] # 交换对应的位置列 reverse_df[['Source location', 'Target location']] = reverse_df[['Target location', 'Source location']] # 如果你需要修改反向行的Value,可以在这里自定义,比如示例中的b-a Value为9 # reverse_df['Value'] = [9, 12, 14, 8, 6] # 可以根据需求设置对应值 # 合并原始行和反向行,去除重复的(Source, Target)对(避免原数据已有双向行时重复) combined_df = pd.concat([df, reverse_df], ignore_index=True) combined_df = combined_df.drop_duplicates(subset=['Source', 'Target'], keep='first') print(combined_df)
说明
- 这段代码会为每一行生成反向行,交换对应的列值
- 如果原数据已经存在某双向配对的两行(比如你的示例中的
x-z和z-x),drop_duplicates会保留原有的两行,不会重复添加 - 你可以根据需求修改
reverse_df['Value']来设置反向行的自定义数值
场景2:确保所有无序配对都有双向行(自定义缺失反向行的内容)
如果你的需求是每个无序配对(比如(a,b))必须同时存在a→b和b→a两行,且对于原数据中不存在的反向行,需要自定义填充Value和位置信息,那么可以用以下方法:
代码实现
import pandas as pd # 你的原始DataFrame df = pd.DataFrame({ 'Source': ['a', 'c', 'c', 'p', 'x'], 'Target': ['b', 'v', 'd', 'q', 'z'], 'Value': [10, 10, 18, 10, 8], 'Source location': [[12.3,1.9], [15.3,1.9], [1.4,31.9], [12.3,1.9], [6.3,1.4]], 'Target location': [[13.5,14.3], [13.5,94.3], [16.6,44.7], [13.5,15.3], [47.5,4.3]] }) # 生成所有唯一的无序配对(排序后确保(a,b)和(b,a)被视为同一对) df['pair'] = df.apply(lambda row: tuple(sorted([row['Source'], row['Target']])), axis=1) unique_pairs = df['pair'].unique() # 构建结果行列表 result_rows = [] for pair in unique_pairs: src1, src2 = pair # 添加正向行(src1→src2),如果原数据存在则复用,否则自定义填充 forward_row = df[(df['Source'] == src1) & (df['Target'] == src2)] if not forward_row.empty: result_rows.append(forward_row.iloc[0].to_dict()) else: result_rows.append({ 'Source': src1, 'Target': src2, 'Value': 0, # 自定义默认值 'Source location': [0.0, 0.0], # 自定义默认位置 'Target location': [0.0, 0.0] }) # 添加反向行(src2→src1),如果原数据存在则复用,否则自定义填充 reverse_row = df[(df['Source'] == src2) & (df['Target'] == src1)] if not reverse_row.empty: result_rows.append(reverse_row.iloc[0].to_dict()) else: # 这里可以根据你的需求自定义反向行的内容,比如示例中的b-a数据 result_rows.append({ 'Source': src2, 'Target': src1, 'Value': 9, 'Source location': [72.9, 18.6], 'Target location': [14.2, 31.6] }) # 转换为最终DataFrame final_df = pd.DataFrame(result_rows).drop(columns='pair') # 移除临时的pair列 print(final_df)
说明
- 这段代码会先识别所有唯一的无序配对,然后为每个配对强制生成双向行
- 对于原数据中已有的行,直接复用;缺失的反向行可以完全自定义填充Value和位置信息
- 最终结果会严格保证每个配对的双向记录都存在
内容的提问来源于stack exchange,提问作者Rahul
相关产品推荐
相关产品推荐

