对每组的一部分进行抽样,但具有最小约束(使用 dplyr)
Sample a proportion of each group, BUT with a minimum constraint (using dplyr)
我有 6 个类别(层)的人口,我想在每个层中取 10% 作为样本。这样做我采取:
var = c(rep("A",10),rep("B",10),rep("C",3),rep("D",5),"E","F");var
value = rnorm(30)
dat = tibble(var,value);
pop=dat%>%group_by(var)
pop
singleallocperce = slice_sample(pop, prop=0.1);
singleallocperce
结果:
# A tibble: 2 x 2
# Groups: var [2]
var value
<chr> <dbl>
1 A -1.54
2 B -1.12
但我想即使在某些层中,它们内部的 polupation 不能达到 10% 的采样率,至少要采取一个 observation.How 我可以在 R 中使用 dplyr 包做到这一点吗?
这是一个可能的解决方案:
sample_func <- function(data) {
standard <- data %>%
group_by(var) %>%
slice_sample(prop = 0.1) %>%
ungroup()
if(!all(unique(data$var) %in% unique(standard$var))) {
mins <- data %>%
filter(!var %in% standard$var) %>%
group_by(var) %>%
slice(1) %>%
ungroup()
}
bind_rows(standard, mins)
}
sample_func(dat)
给出:
var value
<chr> <dbl>
1 A 1.36
2 B -1.03
3 C -0.0450
4 D -0.380
5 E -0.0556
6 F 0.519
假设是,如果您按比例抽样并且 var
没有任何样本,则最小阈值将从 var
中抽取一条记录(通过使用 slice(1)
).
可能的方法(注意 20 x A 的存在以检查是否返回了两个)。
library(tidyverse)
# Data (note 20 As)
var = c(rep("A",20),rep("B",10),rep("C",3),rep("D",5),"E","F")
value = rnorm(40)
dat = tibble(var, value)
# Possible approach
dat %>%
group_by(var) %>%
mutate(min = if_else(n() * 0.1 >= 1, n() * 0.1, 1),
random = sample(n())) %>%
filter(random <= min) |>
select(var, value)
#> # A tibble: 7 × 2
#> # Groups: var [6]
#> var value
#> <chr> <dbl>
#> 1 A 0.0105
#> 2 A 0.171
#> 3 B -1.89
#> 4 C 1.89
#> 5 D 0.612
#> 6 E 0.516
#> 7 F 0.185
由 reprex package (v2.0.1)
创建于 2022-06-02
data.table
library(data.table)
setDT(dat) # make the tibble a data.table
dat[, .SD[sample((1:.N), fifelse(.N >= 10, .N %/% 10, 1))], var]
结果
var value
1: A -0.040487
2: A 0.543354
3: B -1.100892
4: C 0.998006
5: D 0.496898
6: E 0.819967
7: F 0.629236
数据
# Data (note 20 As)
var = c(rep("A",20),rep("B",10),rep("C",3),rep("D",5),"E","F")
value = rnorm(40)
dat = tibble(var, value)
我有 6 个类别(层)的人口,我想在每个层中取 10% 作为样本。这样做我采取:
var = c(rep("A",10),rep("B",10),rep("C",3),rep("D",5),"E","F");var
value = rnorm(30)
dat = tibble(var,value);
pop=dat%>%group_by(var)
pop
singleallocperce = slice_sample(pop, prop=0.1);
singleallocperce
结果:
# A tibble: 2 x 2
# Groups: var [2]
var value
<chr> <dbl>
1 A -1.54
2 B -1.12
但我想即使在某些层中,它们内部的 polupation 不能达到 10% 的采样率,至少要采取一个 observation.How 我可以在 R 中使用 dplyr 包做到这一点吗?
这是一个可能的解决方案:
sample_func <- function(data) {
standard <- data %>%
group_by(var) %>%
slice_sample(prop = 0.1) %>%
ungroup()
if(!all(unique(data$var) %in% unique(standard$var))) {
mins <- data %>%
filter(!var %in% standard$var) %>%
group_by(var) %>%
slice(1) %>%
ungroup()
}
bind_rows(standard, mins)
}
sample_func(dat)
给出:
var value
<chr> <dbl>
1 A 1.36
2 B -1.03
3 C -0.0450
4 D -0.380
5 E -0.0556
6 F 0.519
假设是,如果您按比例抽样并且 var
没有任何样本,则最小阈值将从 var
中抽取一条记录(通过使用 slice(1)
).
可能的方法(注意 20 x A 的存在以检查是否返回了两个)。
library(tidyverse)
# Data (note 20 As)
var = c(rep("A",20),rep("B",10),rep("C",3),rep("D",5),"E","F")
value = rnorm(40)
dat = tibble(var, value)
# Possible approach
dat %>%
group_by(var) %>%
mutate(min = if_else(n() * 0.1 >= 1, n() * 0.1, 1),
random = sample(n())) %>%
filter(random <= min) |>
select(var, value)
#> # A tibble: 7 × 2
#> # Groups: var [6]
#> var value
#> <chr> <dbl>
#> 1 A 0.0105
#> 2 A 0.171
#> 3 B -1.89
#> 4 C 1.89
#> 5 D 0.612
#> 6 E 0.516
#> 7 F 0.185
由 reprex package (v2.0.1)
创建于 2022-06-02data.table
library(data.table)
setDT(dat) # make the tibble a data.table
dat[, .SD[sample((1:.N), fifelse(.N >= 10, .N %/% 10, 1))], var]
结果
var value
1: A -0.040487
2: A 0.543354
3: B -1.100892
4: C 0.998006
5: D 0.496898
6: E 0.819967
7: F 0.629236
数据
# Data (note 20 As)
var = c(rep("A",20),rep("B",10),rep("C",3),rep("D",5),"E","F")
value = rnorm(40)
dat = tibble(var, value)