Python pandas条件随机采样:如何保证抽取的EncounterID全局唯一
全局唯一ID随机采样代码修正
原代码存在的问题
- 多写了一层无意义的内层遍历,会导致同一采样条件反复执行采样,最终结果重复
- 没有跨轮次的ID重复校验,不同采样条件下可能抽到同一个ID,不满足全局唯一要求
- 循环判断逻辑写反,无法触发正确的重采样流程
- 追加结果用了
append,会把整批采样的列表作为单个元素塞进结果,最终返回嵌套列表,不符合输出要求
修正后代码
import pandas as pd def randomSample(df_column, EncounterID_column): ''' 从过滤后的数据集中按规则采样Encounter ID,保证所有采样ID全局唯一 输入参数: df_column - Filtered_df中存储采样标识值的列,即Filtered_df["对应标识列名"] EncounterID_column - Encounter ID对应的列名字符串 返回值: 全局唯一的采样ID列表 ''' Encounters_list = [] df_column = df_column.astype(str) # 遍历所有采样条件 for i in range(len(Samples['Identifier'])): # 筛选当前采样条件对应的数据集 target_identifier = str(Samples['Identifier'][i]) sample_count = int(Samples['Number of Samples'][i]) new_df = Filtered_df[df_column.str.contains(target_identifier, na=False)] # 前置校验:排除已选ID后,剩余可用样本数是否满足采样要求,避免死循环 available_ids = new_df[~new_df[EncounterID_column].isin(Encounters_list)][EncounterID_column].unique() if len(available_ids) < sample_count: raise ValueError(f"标识{target_identifier}下排除已选ID后可用样本数为{len(available_ids)},不足要求的{sample_count}个,无法完成采样") # 循环采样直到本轮所有ID均不与全局已有ID重复 sample_pass = False while not sample_pass: # 不放回抽样,保证本轮内部ID无重复 batch_sample = new_df[EncounterID_column].sample(n=sample_count, replace=False).tolist() # 校验本轮ID和全局已有ID是否存在交集 overlap = set(batch_sample) & set(Encounters_list) if len(overlap) == 0: # 无重复,加入全局结果 Encounters_list.extend(batch_sample) sample_pass = True return Encounters_list
核心逻辑说明
- 单轮采样默认用不放回模式,保证同一轮抽出来的ID不会自己重复
- 每轮抽完立刻校验:只要这批ID里有任何一个已经在之前的结果里,整批作废重抽,直到抽到的全是没出现过的ID才加入最终结果
- 重复判断用集合交集运算,比逐元素遍历列表快很多,数据量大的时候不会卡顿
- 采样前先做容量校验:如果当前条件下没被选过的ID数量不够要抽的数量,直接抛错提示,不会进入无限循环
- 结果追加用
extend,把每个ID单独加进结果列表,保证最终返回的是普通一维列表
如果业务允许同一条ID匹配多个采样标识,可以根据实际需求调整前置校验的过滤规则;如果要求单条ID只能归属一个采样类别,当前逻辑可直接满足要求。
内容的提问来源于stack exchange,提问作者Pat
相关产品推荐
相关产品推荐

