循环中DataFrame采样后无法剔除已采样行的问题求助
问题分析与解决方案
你的代码核心问题有两个:
df.drop(sample)用法错误:drop方法无法直接接收DataFrame列表作为参数,它需要传入要删除的行索引或列名,而你存储的sample是采样后的DataFrame集合,导致剔除操作完全不生效。- 未正确累积已采样标识:没有持续记录所有已被采样的行的唯一标识,后续循环无法识别哪些行已经被选过。
结合你提到的“所有DataFrame是同一大数据集的子集、列结构一致、存在重复行”的场景,分两种情况给出解决方案:
情况1:索引是行的唯一标识(同一索引对应唯一行内容)
如果你的DataFrame索引没有重复,且索引可以唯一代表一行内容,直接累积已采样的索引即可:
import pandas as pd df_list = [df1, df2, df3, df4, df5] samplesizes = [8, 2, 4, 4, 2] max_pop_size = 10 # 请根据实际需求定义这个值 sampled_indices = set() final_samples = [] for df, target_size in zip(df_list, samplesizes): # 剔除已采样过的索引对应的行 df_filtered = df[~df.index.isin(sampled_indices)] # 计算实际可采样的大小:不超过目标数、剩余行数、max_pop_size actual_size = min(target_size, len(df_filtered), max_pop_size) if actual_size == 0: # 没有可采样的行,追加空DataFrame或直接跳过 final_samples.append(pd.DataFrame(columns=df.columns)) continue # 执行采样 current_sample = df_filtered.sample(actual_size, random_state=1000) # 更新已采样索引集合 sampled_indices.update(current_sample.index) # 保存当前采样结果 final_samples.append(current_sample)
情况2:存在重复行(索引不唯一或内容重复但索引不同)
如果不同DataFrame里有内容完全相同的行(即使索引不同),需要基于行内容去重,这时可以把行内容转为元组作为唯一标识:
import pandas as pd df_list = [df1, df2, df3, df4, df5] samplesizes = [8, 2, 4, 4, 2] max_pop_size = 10 sampled_rows = set() final_samples = [] for df, target_size in zip(df_list, samplesizes): # 生成每行内容的元组作为唯一标识 row_tuples = df.apply(tuple, axis=1) # 筛选未被采样过的行 df_filtered = df[~row_tuples.isin(sampled_rows)] # 计算实际采样大小 actual_size = min(target_size, len(df_filtered), max_pop_size) if actual_size == 0: final_samples.append(pd.DataFrame(columns=df.columns)) continue current_sample = df_filtered.sample(actual_size, random_state=1000) # 更新已采样行的集合 sampled_rows.update(current_sample.apply(tuple, axis=1)) final_samples.append(current_sample)
额外注意事项
- 如果你的DataFrame包含不可哈希的列(比如列表类型),用
tuple会报错,此时可以用hashlib生成每行的哈希值作为标识。 max_pop_size必须提前定义,确保它是符合业务需求的数值(比如单次采样的最大上限)。- 所有操作都在DataFrame的副本上进行,不会修改原始的
df_list中的数据。
内容的提问来源于stack exchange,提问作者borisvanax
相关产品推荐
相关产品推荐

