Python如何从数据集抽取无重复第二批样本且支持标记一年后可重新入样
实现方案
核心逻辑围绕两个核心规则设计:一是给每个样本添加唯一标识和抽取时间戳做标记,二是每次抽样前过滤掉仍在1年有效期内的已抽取样本。
前置准备
首先需要给原数据集补充两个必要字段:
- 唯一标识字段(命名为
sample_id):用于区分不同样本,若原数据集没有天然的唯一主键,可以用样本核心字段拼接后取哈希生成 - 上次抽取时间字段(命名为
last_sampled_time):存储样本最近一次被抽取的时间,未被抽取过的样本默认值设为空值
具体执行步骤
- 处理第一批样本的标记
第一批样本抽取完成后,将这批样本的last_sampled_time统一更新为抽取当日的datetime格式时间,存回原数据集。 - 第二批及后续批次抽样逻辑
- 计算有效期阈值:用当前时间减去1年,得到时间分界点,早于该时间的已抽取样本可重新进入候选池
- 过滤候选样本池:从原数据集中筛选满足「从未被抽取过」或「上次抽取时间早于有效期阈值」的样本,作为本次抽样的候选集合
- 按需求从候选集合中抽取对应数量的样本,作为当前批次的输出
- 更新原数据集:将本次新抽取的样本的
last_sampled_time更新为当前抽取时间,存回原数据集完成标记
代码示例(基于Pandas)
import pandas as pd import datetime import hashlib # 辅助函数:无唯一主键时生成样本唯一ID def gen_sample_id(row, key_columns): concat_str = "".join([str(row[col]) for col in key_columns]) return hashlib.md5(concat_str.encode("utf-8")).hexdigest() # 1. 加载原数据集并补全必要字段 df = pd.read_csv("your_raw_dataset.csv") # 补全唯一ID(核心字段根据你的数据集实际情况调整) if "sample_id" not in df.columns: key_cols = ["title", "content", "user_id"] # 替换为你的样本核心字段 df["sample_id"] = df.apply(lambda x: gen_sample_id(x, key_cols), axis=1) # 补全上次抽取时间字段 if "last_sampled_time" not in df.columns: df["last_sampled_time"] = pd.NaT # 2. 计算有效期阈值 expire_threshold = datetime.datetime.now() - datetime.timedelta(days=365) # 若需要精确处理闰年/月份天数差异,可改用dateutil: # from dateutil.relativedelta import relativedelta # expire_threshold = datetime.datetime.now() - relativedelta(years=1) # 3. 过滤候选池 candidate_pool = df[ (df["last_sampled_time"].isna()) | (df["last_sampled_time"] < expire_threshold) ] # 4. 抽样,这里以随机抽1000条为例,可替换为你的抽样规则 batch_sample = candidate_pool.sample(n=1000, random_state=42) # 5. 更新原数据集的抽取标记 df.loc[df["sample_id"].isin(batch_sample["sample_id"]), "last_sampled_time"] = datetime.datetime.now() # 6. 保存结果 df.to_csv("your_raw_dataset_updated.csv", index=False) batch_sample.to_csv("second_batch_samples.csv", index=False)
适配其他存储介质的逻辑
如果你用的是关系型数据库而非本地文件存储数据集,逻辑完全一致:
- 给数据表新增
last_sampled_time字段 - 抽样前用SQL查询过滤候选池:
SELECT * FROM 表名 WHERE last_sampled_time IS NULL OR last_sampled_time < DATE_SUB(NOW(), INTERVAL 1 YEAR) - 抽取完成后更新对应样本的
last_sampled_time为当前时间即可
内容的提问来源于stack exchange,提问作者ChrisPitkin
相关产品推荐
相关产品推荐

