如何在Pandas中生成DataFrame同一行内列的两两组合并保留对应行属性?
解决Pandas中每行风味两两组合并保留关联字段的问题
我明白你的需求了——要把每行里非空的风味列生成所有两两组合,同时保留该行对应的price和id,还要排除包含NaN的组合。你的原代码问题在于只对列名做了组合,没有针对每行的非空值处理,也没关联上price和id字段。下面给你两种可行的解决方案:
方法一:逐行处理(直观易懂,适合小数据集)
这种方法直接对每行应用自定义函数,先过滤掉该行的NaN风味值,再生成两两组合,最后把组合和该行的price、id绑定:
import pandas as pd import itertools def generate_flavor_pairs(row): # 提取当前行所有非NaN的风味值 valid_flavors = row.filter(like='flavor_').dropna().tolist() # 生成所有两两组合(不考虑顺序,因为是combinations而非permutations) flavor_pairs = itertools.combinations(valid_flavors, 2) # 为每个组合添加price和id,返回字典列表 return [ {'Target': pair[0], 'Source': pair[1], 'Price': row['price'], 'id': row['id']} for pair in flavor_pairs ] # 应用函数到每一行,然后展开所有结果为新DataFrame df_new = pd.DataFrame([ item for row in df1.apply(generate_flavor_pairs, axis=1) for item in row ])
方法二:长表转换+分组处理(性能更优,适合大数据集)
如果你的数据集很大,逐行apply可能效率偏低,推荐先把宽表转成长表,再按price和id分组生成组合:
import pandas as pd import itertools # 第一步:把所有风味列转成长格式,保留price和id,同时去掉NaN行 flavor_long = df1.melt( id_vars=['price', 'id'], value_vars=df1.filter(like='flavor_'), value_name='flavor' ).dropna(subset=['flavor']) # 第二步:对每个(price, id)分组,生成两两组合 def get_group_pairs(group): pairs = list(itertools.combinations(group['flavor'], 2)) # 生成组内的组合DataFrame,并关联price和id return pd.DataFrame(pairs, columns=['Target', 'Source']).assign( Price=group['price'].iloc[0], id=group['id'].iloc[0] ) # 应用分组函数并整理结果 df_new = flavor_long.groupby(['price', 'id']).apply(get_group_pairs).reset_index(drop=True)
关键说明
- 排除NaN组合:两种方法都是先过滤掉每行/每组的NaN风味值,所以生成的组合自然不会包含NaN,无需额外处理。
- 组合顺序:用
itertools.combinations生成的是无序组合(比如(Lemon, Grape)和(Grape, Lemon)只会保留前者),如果需要有序组合,换成itertools.permutations即可。 - 自定义范围:如果只想用特定的风味列(比如排除
flavor_1),只需要在过滤时调整,比如把row.filter(like='flavor_')改成row[['flavor_2', 'flavor_3', ...]]。
内容的提问来源于stack exchange,提问作者DAEHYUN KIM
相关产品推荐
相关产品推荐

