You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

逻辑说明:

  1. 提取可选水果:先按subj分组,整理出每个受试者能选的所有水果
  2. 分配不重复水果:在每个event组内,依次给受试者分配未被使用过的可选水果,确保同组内水果不重复
  3. 整理结果:合并分配好的水果与原数据,去重后得到符合要求的DataFrame

内容的提问来源于stack exchange,提问作者user15141497

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 08:10:46