You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用dplyr对K个不同样本量分组抽取floor(n[k]*p)样本的问题

解决分组内按不同数量抽样的问题

这问题我碰到过!确实sample_n()没法直接用,因为它要求size参数是一个全局标量,不能跟着每个分组动态变化。不过用tidyverse的工具完全能搞定,给你两种符合规范的解决方案:

方法1:用slice_sample()(推荐)

dplyr从1.0.0版本开始推荐用slice_sample()替代sample_n(),它最大的优势就是支持在分组上下文里计算抽样数量——正好满足你的需求!

假设你要按比例p抽样(比如你例子里的p=0.5对应floor(n()/2)),代码可以这么写:

library(dplyr)

# 替换成你的数据框和分组列,p是抽样比例
df %>%
  group_by(my_group) %>%
  slice_sample(n = floor(n() * p)) %>%
  ungroup()  # 按需取消分组

测试示例

我们用模拟数据验证一下:

set.seed(123)  # 固定随机种子,结果可复现
df <- tibble(
  my_group = rep(c("A", "B", "C"), c(5, 7, 4)),  # A组5个,B组7个,C组4个
  value = rnorm(16)
)

# 按50%比例抽样,每个组抽floor(n*0.5)个
df %>%
  group_by(my_group) %>%
  slice_sample(n = floor(n() * 0.5))

运行后你会看到:

  • A组5个元素抽2个
  • B组7个元素抽3个
  • C组4个元素抽2个
    完全符合预期!

方法2:用group_modify()

如果你习惯用更“显式”的分组处理逻辑,group_modify()也能实现。它会对每个分组的数据框单独操作:

df %>%
  group_by(my_group) %>%
  group_modify(~ slice_sample(.x, n = floor(nrow(.x) * p))) %>%
  ungroup()

这里.x代表每个分组的子数据框,nrow(.x)就是当前组的元素数量,逻辑和第一种方法一致,只是写法更繁琐一点。

为什么原来的代码不行?

你之前的代码sample_n(n_samples)报错,是因为sample_n()的size参数只能接受一个单一数值,不能是分组内生成的变量列。而slice_sample()允许传入一个表达式,这个表达式会在每个分组的上下文里计算,所以能动态获取每个组的抽样数量。

内容的提问来源于stack exchange,提问作者gsmafra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:24:54