如何用Pandas处理近重复行:为每个Subject分配唯一不同Fruit
问题描述
我有一个Pandas DataFrame,其中行几乎完全重复,仅fruit列的值不同:
import pandas as pd event = [1, 1, 1, 1, 2, 2, 2, 2, 3, 3] subj = [1, 1, 2, 2, 3, 3, 4, 4, 5, 6] age = [22, 22, 56, 56, 32, 32, 48, 48, 19, 43] sex = ['F', 'F','M',' M', 'M', 'M',' F',' F', 'F', 'M'] fruit = ['apple', 'orange', 'apple', 'orange', 'grape', 'mango', 'grape', 'mango', 'apple', 'mango'] df = pd.DataFrame(list(zip(event, subj, age, sex, fruit)), columns =['event', 'subj', 'age', 'sex', 'fruit'])
需求:
- 每个
subj仅保留一行(对应一种水果) - 同一
event内的subj对应的fruit不能重复 - 数据量极大,无法手动筛选;之前用
duplicated()只能保留首/尾行,会导致同event内多个subj水果重复
补充规则:
- 每个
event内的subj唯一(原数据已满足) - 每个
subj仅属于一个event
解决方案
可以通过按event分组+自定义水果分配逻辑实现需求,核心是在每个活动组内,给受试者轮流分配不重复的可选水果:
import pandas as pd # 构建原DataFrame event = [1, 1, 1, 1, 2, 2, 2, 2, 3, 3] subj = [1, 1, 2, 2, 3, 3, 4, 4, 5, 6] age = [22, 22, 56, 56, 32, 32, 48, 48, 19, 43] sex = ['F', 'F','M',' M', 'M', 'M',' F',' F', 'F', 'M'] fruit = ['apple', 'orange', 'apple', 'orange', 'grape', 'mango', 'grape', 'mango', 'apple', 'mango'] df = pd.DataFrame(list(zip(event, subj, age, sex, fruit)), columns =['event', 'subj', 'age', 'sex', 'fruit']) def process_event_group(group): # 提取每个受试者对应的所有可选水果 subj_available_fruits = group.groupby('subj')['fruit'].unique().reset_index() # 获取当前活动组的所有可选水果类型 all_fruit_options = group['fruit'].unique() used_fruits = [] assigned_fruits = [] # 给每个受试者分配未被使用的水果 for _, row in subj_available_fruits.iterrows(): # 筛选当前受试者可选且未被其他人选过的水果 available = [f for f in row['fruit'] if f not in used_fruits] if available: selected = available[0] assigned_fruits.append(selected) used_fruits.append(selected) else: # 极端情况:所有可选水果都被用了,默认选第一个(可按需调整) assigned_fruits.append(row['fruit'][0]) # 合并分配结果并整理格式 subj_available_fruits['selected_fruit'] = assigned_fruits merged = group.merge(subj_available_fruits[['subj', 'selected_fruit']], on='subj') # 每个受试者只保留一行,并重命名列 final_group = merged.drop_duplicates('subj').drop('fruit', axis=1).rename(columns={'selected_fruit': 'fruit'}) return final_group # 按event分组处理,合并结果 df_new = df.groupby('event', group_keys=False).apply(process_event_group).reset_index(drop=True) print(df_new)
运行结果:
event subj age sex fruit 0 1 1 22 F apple 1 1 2 56 M orange 2 2 3 32 M grape 3 2 4 48 F mango 4 3 5 19 F apple 5 3 6 43 M mango
逻辑说明:
- 提取可选水果:先按
subj分组,整理出每个受试者能选的所有水果 - 分配不重复水果:在每个
event组内,依次给受试者分配未被使用过的可选水果,确保同组内水果不重复 - 整理结果:合并分配好的水果与原数据,去重后得到符合要求的DataFrame
内容的提问来源于stack exchange,提问作者user15141497
相关产品推荐
相关产品推荐

