使用特定于组的样本大小从数据框中采样

use*_*544 5 r sample dplyr

我想使用每个组中不相等的样本大小从数据框中对行进行采样。

假设我们有一个按“组”分组的简单数据框:

library(dplyr)
set.seed(123)

df <- data.frame(group = rep(c("A", "B"), each = 10), 
                 value = rnorm(10))
df
#>    group       value
#> 1      A -0.56047565
#> 2      A -0.23017749
#> .....
#> 10     A -0.44566197
#> 11     B -0.56047565
#> 12     B -0.23017749
#> .....
#> 20     B -0.44566197
Run Code Online (Sandbox Code Playgroud)

使用包中的slice_sample函数dplyr,您可以轻松从此数据框中切出相同大小的组:

df %>% group_by(group) %>% slice_sample(n = 2) %>% ungroup()

#> # A tibble: 4 x 2
#>   group  value
#>   <fct>  <dbl>
#> 1 A     -0.687
#> 2 A     -0.446
#> 3 B     -0.687
#> 4 B      1.56
Run Code Online (Sandbox Code Playgroud)

您如何从每个组(大小不等的切片组)中采样不同数量的值?例如,从 A 组中抽取 4 行,从 B 组中抽取 5 行?

小智 11

我能想到的最简单的事情是map2使用purrr.

library(dplyr)
library(purrr)

df %>% 
  group_split(group) %>% 
  map2_dfr(c(4, 5), ~ slice_sample(.x, n = .y))
Run Code Online (Sandbox Code Playgroud)
# A tibble: 9 x 2
  group   value
  <chr>   <dbl>
1 A     -0.687 
2 A      1.56  
3 A      0.0705
4 A      1.72  
5 B     -0.560 
6 B      0.461 
7 B      0.129 
8 B      0.0705
9 B     -0.230 
Run Code Online (Sandbox Code Playgroud)

需要注意的是,您需要了解拆分的顺序。我认为group_split()将按照因素对组进行排序。解决这个问题的方法是像这样进行调整,并n从命名向量中查找 。

group_slice_n <- c(A = 4, B = 5)

df %>% 
  split(.$group) %>% 
  imap_dfr(~ slice_sample(.x, n = group_slice_n[.y]))
Run Code Online (Sandbox Code Playgroud)


r2e*_*ans 6

尝试这个:

group_sizes <- tibble(group = c("A", "B"), size = c(4, 5))
set.seed(2021)
df %>%
  left_join(group_sizes, by = "group") %>%
  group_by(group) %>%
  mutate(samp = sample(n())) %>%
  filter(samp <= size) %>%
  ungroup()
# # A tibble: 9 x 4
#   group   value  size  samp
#   <chr>   <dbl> <dbl> <int>
# 1 A      0.0705     4     2
# 2 A      0.129      4     4
# 3 A     -0.687      4     1
# 4 A     -0.446      4     3
# 5 B     -0.560      5     5
# 6 B      1.56       5     1
# 7 B      0.129      5     4
# 8 B      1.72       5     3
# 9 B     -1.27       5     2
Run Code Online (Sandbox Code Playgroud)