按组随机抽样并基于结果筛选:R语言DataFrame处理问询
按组随机抽样并筛选R DataFrame的解决方案
我来帮你搞定这个按组随机抽样加筛选的需求哈~先从你的数据说起,先确认下你的数据构造代码(我把第一个value改成了4.5,贴合你给出的示例表格):
l_ids = c(1, 1, 1, 2, 2, 2, 2) l_months = c(5, 5, 5, 88, 88, 88, 88) l_calWeek = c(201708, 201709, 201710, 201741, 201742, 201743, 201744) value = c(4.5, 6, 3, 99, 100, 1001, 1002) dat <- setNames(data.frame(cbind(l_ids, l_months, l_calWeek, value)), c("ids", "months", "calWeek", "value"))
你的核心需求是按ids分组进行随机抽样,再基于抽样结果筛选数据,我分几种常见的应用场景给你实现方案:
场景1:每个组随机抽取固定数量的行
如果需要每个ids组随机抽指定行数(比如1行),用dplyr包处理分组操作会非常便捷:
首先加载依赖包:
library(dplyr)
然后执行抽样筛选:
# 设置随机种子,保证抽样结果可重复 set.seed(123) # 每个ids组随机抽取1行,replace=FALSE表示不允许重复抽样 sampled_dat <- dat %>% group_by(ids) %>% sample_n(size = 1, replace = FALSE) %>% ungroup()
如果需要每个组抽2行,直接把size=2即可;如果组内行数少于指定的抽样数量,可以把replace=TRUE开启,允许重复抽样。
场景2:每个组按比例随机抽样
如果需要按比例抽取每个组的行(比如每个组抽30%),可以用sample_frac函数:
set.seed(123) sampled_dat_frac <- dat %>% group_by(ids) %>% sample_frac(size = 0.3, replace = FALSE) %>% ungroup()
这个方法会自动按组内行数的比例计算抽样数量,结果会四舍五入取整。
场景3:每个组随机抽取一个唯一calWeek,保留对应所有行
如果你的需求是先给每个组随机选一个calWeek,再保留该组中属于这个calWeek的所有行(适合组内同一calWeek有多行的情况),可以这么做:
set.seed(123) # 第一步:每个组随机选一个唯一的calWeek selected_weeks <- dat %>% group_by(ids) %>% distinct(calWeek) %>% # 先去重组内的calWeek sample_n(size = 1) %>% ungroup() # 第二步:筛选原数据中匹配ids和选中calWeek的行 filtered_dat <- dat %>% inner_join(selected_weeks, by = c("ids", "calWeek"))
不用dplyr的基础R实现
如果你不想加载额外包,用基础R也能实现每个组固定行数的抽样:
set.seed(123) # 按ids拆分数据,对每个组抽样1行后合并 sampled_dat_base <- do.call(rbind, lapply(split(dat, dat$ids), function(x) x[sample(nrow(x), 1), ]))
内容的提问来源于stack exchange,提问作者clog14




