【问题标题】:Is there a way to draw random subgroups from all groups in a nested dataset in R? [duplicate]有没有办法从 R 的嵌套数据集中的所有组中抽取随机子组? [复制]
【发布时间】:2021-12-24 15:40:01
【问题描述】:

我正在尝试使用较小的样本,因为否则 brms 和 rstan 模型将永远在我的完整数据集上运行。为了做到这一点,我需要通过从所有个国家随机抽取一定数量的 X 所学校来减少我的样本量。它是一个嵌套数据集,学生在课堂上,在学校中嵌套,在国家/地区嵌套。

我不能从数据集中随机抽取学校,因为这可能会导致不包括所有国家/地区,而且由于国家/地区之间的标签相似,我也可能不知道发生了什么。

这里是模拟的样子。请注意,学校的规模与此处不同。

mydata <- data.frame(country =c(rep("Germany", 20), rep("Italy", 20),rep("France", 20)),
                 school  =c(rep("A", 5), rep("B", 5), rep("C", 5), rep("D", 5)),
                 student.age     = sample(18:30, 60, replace=TRUE),
                 var1            = rnorm(60,0,1))

我在网上找到了一个函数here,它可以完成这项工作,但仅适用于第一个分组因素,即国家:它随机选择 x 个国家及其所有行。

sample_n_groups = function(tbl, size, replace = FALSE, weight = NULL) {
  # regroup when done
  grps = tbl %>% groups %>% lapply(as.character) %>% unlist
  # check length of groups non-zero
  keep = tbl %>% summarise() %>% ungroup() %>% sample_n(size, replace, weight)
  # keep only selected groups, regroup because joins change count.
  # regrouping may be unnecessary but joins do something funky to grouping variable
  tbl %>% right_join(keep, by=grps) %>% group_by_(.dots = grps)
}

但将其应用于第二级分组(在国家/地区内随机抽取组样本,它会失败。

mydata %>% 
  group_by(country, school) %>% 
  sample_n_groups(2)

所以我的问题是:有没有 tidyverse(或 R 中的任何其他方式)的方式?为了更详细,我需要例如来自所有国家、意大利、德国等的 2 所随机学校。这些学校的规模各不相同,而且各国之间的编码几乎总是相同的。

【问题讨论】:

  • 这能回答你的问题吗? Randomly sample groups
  • 不,因为答案主要有两个问题:它们要么不返回完整的组(它们在组内采样),要么忽略数据的嵌套性质。在我介绍的情况下,我需要对类别内的完整组进行抽样。不过还是谢谢你。
  • @GeorgeGL 你可以试试这个:mydata %&gt;% group_by(country, school) %&gt;% slice_sample() %&gt;% group_by(country) %&gt;% slice_sample(n = 2)

标签: r dplyr


【解决方案1】:

library(tidyverse)
df %>% 
  group_by(Country) %>% 
  slice_sample(n = 3)
#> # A tibble: 6 x 4
#> # Groups:   Country [2]
#>   Country School Class Student
#>   <chr>    <int> <int>   <int>
#> 1 Germany      1     2       1
#> 2 Germany      1     1       1
#> 3 Germany      1     1       2
#> 4 Italy        1     2       1
#> 5 Italy        1     2       3
#> 6 Italy        2     2       1

# or

library(sampling)
sample_strata <- strata(
  data = df,
  stratanames = c("Country"),
  size = c(2, 3),
  method = "srswor"
)

sample_strata
#>    Country ID_unit      Prob Stratum
#> 3    Italy       3 0.2857143       1
#> 4    Italy       4 0.2857143       1
#> 9  Germany       9 0.6000000       2
#> 11 Germany      11 0.6000000       2
#> 12 Germany      12 0.6000000       2

df[sample_strata$ID_unit, ]
#>    Country School Class Student
#> 3    Italy      1     2       1
#> 4    Italy      1     2       2
#> 9  Germany      1     1       2
#> 11 Germany      2     1       1
#> 12 Germany      2     2       1

reprex package (v2.0.1) 于 2021 年 12 月 24 日创建

数据

df <- structure(
  list(
    Country = c(
      "Italy",
      "Italy",
      "Italy",
      "Italy",
      "Italy",
      "Italy",
      "Italy",
      "Germany",
      "Germany",
      "Germany",
      "Germany",
      "Germany"
    ),
    School = c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 2L, 2L),
    Class = c(1L, 1L, 2L, 2L, 2L, 1L, 2L, 1L, 1L, 2L, 1L, 2L),
    Student = c(1L, 2L, 1L, 2L, 3L, 1L, 1L, 1L, 2L, 1L, 1L, 1L)
  ),
  class = "data.frame",
  row.names = c(NA,-12L)
)

【讨论】:

  • slice_sample(),不起作用,因为它不会选择整个学校...
【解决方案2】:

另一种使用data.table的方法

library(data.table)
setDT(df)

df[df[ , .I[sample(.N, 3)] , by = Country]$V1]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-28
    • 2020-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-29
    • 1970-01-01
    相关资源
    最近更新 更多