如何基于最小样本的Date_Diff分布对数据框分组抽样?
匹配基准分布的分层抽样实现
我明白你想要的是匹配目标分布的分层抽样——也就是让Y、Z这些物种的抽样结果,Date_Diff的分布和最小样本的X物种保持一致,而不是单纯随机抽取相同数量的样本。咱们可以通过分层抽样的方式来实现,具体步骤如下:
1. 先获取基准物种(X)的Date_Diff分布
首先我们需要统计X物种中每个Date_Diff值的出现比例,再根据目标样本量(25)计算出每个Date_Diff类别需要抽取的数量:
# 生成基准分布表 base_dist <- df %>% filter(Veg_Species == 'X') %>% count(Date_Diff, name = "base_count") %>% # 统计每个Date_Diff的数量 mutate(base_prop = base_count / sum(base_count)) %>% # 计算比例 mutate(target_n = round(base_prop * 25)) # 计算每个类别需要抽取的数量
2. 对单个物种(比如Z)进行匹配分布的抽样
有了基准分布后,我们可以针对单个物种,按Date_Diff分层抽取对应数量的样本:
sample_z <- df %>% filter(Veg_Species == 'Z') %>% group_by(Date_Diff) %>% sample_n( # 匹配基准分布的目标抽取数量 size = base_dist$target_n[match(Date_Diff, base_dist$Date_Diff)], # 如果当前类别数量不足,允许有放回抽样(避免报错) replace = ifelse(n() < base_dist$target_n[match(Date_Diff, base_dist$Date_Diff)], TRUE, FALSE) ) %>% ungroup()
3. 封装成通用函数,批量处理所有物种
如果需要对所有物种统一处理,可以把逻辑封装成函数,这样更高效:
sample_match_dist <- function(data, base_species, target_n) { # 第一步:获取基准物种的分布 base_dist <- data %>% filter(Veg_Species == base_species) %>% count(Date_Diff, name = "base_count") %>% mutate(base_prop = base_count / sum(base_count)) %>% mutate(target_n = round(base_prop * target_n)) # 第二步:对每个物种应用分层抽样 data %>% group_by(Veg_Species) %>% group_modify(function(group, .key) { group %>% group_by(Date_Diff) %>% sample_n( size = base_dist$target_n[match(Date_Diff, base_dist$Date_Diff)], replace = ifelse(n() < base_dist$target_n[match(Date_Diff, base_dist$Date_Diff)], TRUE, FALSE) ) %>% ungroup() }) %>% ungroup() } # 调用函数:以X为基准,每个物种抽取25条,匹配X的Date_Diff分布 matched_samples <- sample_match_dist(df, base_species = 'X', target_n = 25)
关键说明
- 这里的核心是分层抽样:按照
Date_Diff分组,每个组内抽取对应数量的样本,保证整体分布和基准一致 replace = TRUE的设置是为了应对某些Date_Diff在目标物种中数量不足的情况,如果你的数据中每个Date_Diff的数量都足够,可以把这个参数设为FALSE- 如果你觉得四舍五入导致的总数偏差可以接受,直接用上面的代码就行;如果需要严格保证每个物种抽样总数是25,可以在最后调整个别组的抽取数量(比如把多的一条调整到数量充足的组)
内容的提问来源于stack exchange,提问作者Corbjn
相关产品推荐
相关产品推荐

