在R中按diet分组随机抽取2个species并保留对应所有行的方法
分组随机抽取指定数量物种并保留所有对应行的实现方法
原始数据
# 构造示例数据框df df <- data.frame( species = c("blue", "blue", "red", "yellow", "yellow", "yellow", "black", "white", "maroon", "orange", "orange", "orange"), diet = c(rep("round", 6), rep("square", 6)), row.names = paste0("a", 1:12) )
需求说明
针对diet的每个分组,随机抽取2个不重复的species,同时保留该物种对应的所有行;理想状态下可循环执行多次,且每次抽取的物种不重复。
单次抽取实现
利用dplyr的分组筛选逻辑,先在每个diet分组内随机选2个唯一物种,再匹配回原数据保留所有对应行:
library(dplyr) # 设置随机种子保证结果可复现 set.seed(123) single_result <- df %>% group_by(diet) %>% # 每组内随机选取2个唯一species filter(species %in% sample(unique(species), size = 2)) %>% ungroup() # 查看结果 print(single_result)
运行后输出示例:
# A tibble: 5 × 2 species diet <chr> <chr> 1 blue round 2 blue round 3 red round 4 black square 5 white square
多次无重复抽取实现
如果需要循环多次抽取且同一分组内的物种不会重复被选中,可以编写如下函数:
# 定义多次无重复抽取函数 repeat_sample_species <- function(data, num_per_group = 2, repeat_times = 3) { # 初始化结果列表和已抽取物种记录 result_list <- list() sampled_tracker <- data %>% distinct(diet, species) %>% mutate(is_sampled = FALSE) for(i in 1:repeat_times) { # 筛选每个分组中未被抽取的物种,随机选指定数量 target_species <- sampled_tracker %>% group_by(diet) %>% filter(!is_sampled) %>% # 若剩余物种不足指定数量,取全部剩余 slice_sample(n = min(num_per_group, n())) %>% ungroup() # 无可用物种时提前终止循环 if(nrow(target_species) == 0) break # 匹配原数据得到本次抽取结果 current_result <- data %>% inner_join(target_species %>% select(diet, species), by = c("diet", "species")) # 更新已抽取记录 sampled_tracker <- sampled_tracker %>% left_join(target_species %>% mutate(is_sampled = TRUE), by = c("diet", "species")) %>% mutate(is_sampled = coalesce(is_sampled.y, is_sampled.x)) %>% select(-is_sampled.x, -is_sampled.y) # 存入结果列表 result_list[[i]] <- current_result } return(result_list) } # 调用函数执行3次无重复抽取 set.seed(456) repeated_results <- repeat_sample_species(df, num_per_group = 2, repeat_times = 3) # 查看第一次抽取结果 print(repeated_results[[1]]) # 查看第二次抽取结果 print(repeated_results[[2]])
这个函数会自动跳过已经抽取过的物种,直到指定次数执行完毕或分组内无剩余物种可选。
内容的提问来源于stack exchange,提问作者Sam Degregori
相关产品推荐
相关产品推荐

