如何从指定数据框中均匀抽样,且每个谱系仅保留一个代表?
解决方案
第一步:先为每个谱系(V4)保留唯一代表
你需要先确保每个谱系只留下一个样本,后续再对这些去重后的样本做均匀抽样。这里提供两种常用方式:
- 随机选取每个谱系的一个样本:
# 每个谱系随机抽取1个样本 lineage_unique <- tb_profiler_barcodes %>% group_by(V4) %>% slice_sample(n = 1) %>% ungroup()
- 选取每个谱系中position最接近中位数的样本(更具代表性):
# 每个谱系选position最接近该谱系中位数的样本 lineage_unique <- tb_profiler_barcodes %>% group_by(V4) %>% mutate(median_pos = median(V2)) %>% slice(which.min(abs(V2 - median_pos))) %>% ungroup() %>% select(-median_pos) # 移除辅助计算列
第二步:对去重后的样本做均匀抽样
基于第一步得到的lineage_unique,可以通过以下两种方法实现position的均匀抽样:
方法一:分箱抽取
将整个position范围分成指定数量的区间,每个区间选取一个样本:
# 设置分箱数量(可根据需求调整) bin_count <- 150 uniform_samples <- lineage_unique %>% arrange(V2) %>% # 按position范围分箱 mutate(bin = cut(V2, breaks = bin_count, labels = FALSE)) %>% # 每个箱选一个样本(也可换成slice_sample随机选) group_by(bin) %>% slice(1) %>% ungroup() %>% select(-bin) # 移除分箱标记列
方法二:匹配均匀目标位置
生成均匀分布的目标position,匹配每个目标位置最近的样本:
# 设置需要抽取的样本数量 sample_count <- 150 # 获取去重样本的position范围 pos_range <- range(lineage_unique$V2) # 生成均匀分布的目标位置 target_pos <- seq(pos_range[1], pos_range[2], length.out = sample_count) # 为每个目标位置匹配最近的样本 uniform_samples <- purrr::map_dfr(target_pos, function(pos) { lineage_unique %>% slice(which.min(abs(V2 - pos))) %>% mutate(target_position = pos) }) %>% distinct(V4, .keep_all = TRUE) # 确保同一个谱系不会被重复选中
注意事项
- 如果你的谱系总数少于设置的抽样数,最终样本数会等于谱系总数(因为每个谱系只能保留一个)
- 可根据需求灵活调整
bin_count或sample_count的值 - 你之前的代码存在变量名错误:
binned_sorted <- sorted_df %>% ...中的sorted_df应改为sorted_barcodes
内容的提问来源于stack exchange,提问作者Mary
相关产品推荐
相关产品推荐

