如何在R中对数据集进行偏向近期日期的平滑随机抽样?
问题描述
我在R中有如下数据集:
date = sample(seq(as.Date('2015-01-01'), as.Date('2022-08-12'), by = "day"), 1000) var1 = rnorm(1000, 1000,1000) var2 = rnorm(1000, 1000,1000) var3 = rnorm(1000, 1000,1000) question_data = data.frame(date, var1, var2, var3) question_data$id = 1:nrow(question_data)
我希望从该数据集中抽取1000个随机样本,要求靠近当前日期的样本数量多于起始日期的样本。
我采用了一种简单方法:先按日期倒序排序数据集:
question_data <- question_data[order(-question_data$date),]
然后创建新的date_id:
question_data$date_id = 1:nrow(question_data)
接着设定阈值进行加权抽样:
part_1 <- question_data[which(question_data$date_id > 750), ] part_2 <- question_data[which(question_data$date_id < 750), ] library(dplyr) random_sample = data.frame(sample_n(part_1, 250, replace = TRUE), sample_n(part_2, 500, replace = TRUE))
请问是否有更优的实现方式?比如能实现平滑随机抽样的方法?
更优的平滑加权抽样方法
你的分块抽样方法逻辑简单,但权重是阶梯式突变的,抽样结果的日期分布不够平滑。可以通过给每个样本分配与日期正相关的连续权重,实现抽样概率随日期推移逐渐升高的效果,以下是几种实用方案:
方案1:线性加权抽样(base R)
将日期转换为距离起始日期的天数,以此作为权重基础,越晚的日期权重越大:
# 计算每个日期距离最早日期的天数 question_data$days_since_start <- as.numeric(question_data$date - min(question_data$date)) # 归一化权重(可选,避免权重数值过大) question_data$weight <- question_data$days_since_start / max(question_data$days_since_start) # 设置随机种子保证结果可复现 set.seed(123) # 带权重抽取1000个样本(replace=TRUE允许重复抽样) random_sample <- question_data[sample(nrow(question_data), size=1000, replace=TRUE, prob=question_data$weight), ]
方案2:指数加权抽样(dplyr)
如果需要让近期样本的抽样概率提升更显著,可以用指数函数放大权重差距:
library(dplyr) set.seed(123) random_sample <- question_data %>% # 计算日期的相对位置(0对应最早日期,1对应最晚日期) mutate(rel_date = as.numeric(date - min(date)) / as.numeric(max(date) - min(date))) %>% # 指数权重,gamma值越大,近期样本权重越高(可根据需求调整) mutate(weight = exp(3 * rel_date)) %>% # 按权重抽样 slice_sample(n=1000, replace=TRUE, weight_by=weight)
方案3:基于日期排名的平滑加权
若不想依赖日期的绝对差值,也可以用日期的排名作为权重:
# 按日期升序排名,越晚的日期排名值越高 question_data$date_rank <- rank(question_data$date) set.seed(123) random_sample <- question_data[sample(nrow(question_data), size=1000, replace=TRUE, prob=question_data$date_rank), ]
这些方法的优势:
- 权重连续变化,抽样概率随日期平滑提升,避免分块抽样的突变效应
- 可灵活调整权重增长幅度(比如指数加权中的gamma参数),适配不同的抽样需求
- 代码更简洁,无需手动分块处理
内容的提问来源于stack exchange,提问作者stats_noob
相关产品推荐
相关产品推荐

