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

如何在pandas DataFrame中按比例随机删除指定列重复行

解决方案

原有代码失效原因

你之前写的代码逻辑不符合需求:先全局随机采样50%行后调用drop_duplicates(subset=['A']),会直接把A列所有重复值的行全部删除,最终每个A的取值只会保留1行,完全达不到「按A列分组、每组删除指定比例行」的效果。
正确实现的核心逻辑是:按A列对数据分组,每个分组单独随机采样保留对应比例的行,最后把所有分组合并为新的DataFrame。

基础需求:所有分组统一删除50%行

直接按A列分组,每组采样50%的行保留即可,代码如下:

# 每组随机保留50%行,删除剩余50%
df_basic = df.groupby('A', group_keys=False).apply(
    lambda x: x.sample(frac=0.5)
).reset_index(drop=True)

如果需要结果可复现,可以在sample()中传入random_state=固定整数参数固定随机种子。运行后pandas会自动对每组保留的行数做取整处理,输出结构和你给出的示例一致。

进阶需求:每个分组按自定义随机比例删除行

首先把A列的唯一值和生成的随机删除比例做键值对映射,分组采样时根据当前分组的取值读取对应的保留比例即可,全程不需要硬编码:

import random

# 获取A列所有唯一值,顺序和生成随机比例列表的顺序对齐
a_unique = df['A'].unique()
# 生成每个分组对应的删除比例,取值范围30%-50%
del_percent_list = [random.randint(30, 50) for _ in range(len(a_unique))]
# 构建A值到保留比例的映射:保留比例 = 1 - 删除比例/100
keep_ratio_map = {val: (100 - p)/100 for val, p in zip(a_unique, del_percent_list)}

# 按分组采样对应比例的行
df_adv = df.groupby('A', group_keys=False).apply(
    lambda x: x.sample(frac=keep_ratio_map[x.name])
).reset_index(drop=True)

如果需要精确控制每组保留行数的取整规则(比如固定向上取整、向下取整),可以改用n参数指定保留行数,示例如下:

import math

# 每组保留行数向上取整
df_adv = df.groupby('A', group_keys=False).apply(
    lambda x: x.sample(n=math.ceil(len(x) * keep_ratio_map[x.name]))
).reset_index(drop=True)

注意事项

  • 生成随机比例列表时,要保证df['A'].unique()的取值顺序和生成列表的顺序一一对应,使用字典映射可以避免后续顺序错乱导致比例匹配错误
  • groupby时设置group_keys=False是为了避免把分组键加到结果的多层索引里,减少后续重置索引的额外处理
  • 如果需要更直观的删除逻辑,也可以对每组采样要删除的行索引,再调用drop()方法删除对应行,和采样保留的逻辑完全等价

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 15:30:05