在 case_when 中创建 tidyeval 函数
Making tidyeval function inside case_when
我有一个数据集,我喜欢根据这些值的概率分布来估算其中的一个值。让我们先做一些可重现的例子
library(tidyverse)
library(janitor)
dummy1 <- runif(5000, 0, 1)
dummy11 <- case_when(
dummy1 < 0.776 ~ 1,
dummy1 < 0.776 + 0.124 ~ 2,
TRUE ~ 5)
df1 <- tibble(q1 = dummy11)
这是输出:
df1 %>% tabyl(q1)
q1 n percent
1 3888 0.7776
2 605 0.1210
5 507 0.1014
我使用 mutate
和 sample
在值 1 和 2 之间共享值 = 5,如下所示:
df1 %>%
mutate(q1 = case_when(q1 == 5 ~ sample(
2,
length(q1),
prob = c(0.7776, 0.1210),
replace = TRUE
),
TRUE ~ as.integer(q1))
)
结果如下:
q1 n percent
1 4322 0.8644
2 678 0.1356
这种方法似乎可行,但是因为我需要将其应用于多个变量,所以我尝试编写一个函数来使用 tidyverse 和 tidyeval
,就像这样
my_impute <- function(.data, .prob_var, ...) {
.prob_var <- enquo(.prob_var)
.data %>%
sample(2, prob=c(!!.prob_var), replace = TRUE)
}
# running on data
df1 %>%
mutate(q1 = case_when(q1 == 5 ~ !!my_impute(q1),
TRUE ~ as.integer(q1))
)
错误是:
Error in eval_tidy(pair$lhs, env = default_env) : object 'q1' not found
我们需要 tabyl
生成的 'percent' 列中的 prob
值,因此可以将函数修改为
library(janitor)
library(dplyr)
my_impute <- function(.data, .prob_var, vals, ...) {
.prob_var = enquo(.prob_var)
.prob_vals <- .data %>%
janitor::tabyl(!!.prob_var) %>%
filter(!!.prob_var %in% vals) %>%
pull(percent)
.data %>%
mutate(!! .prob_var := case_when(!! .prob_var == 5 ~
sample(
2,
n(),
prob = .prob_vals,
replace = TRUE
),
TRUE ~ as.integer(q1))
)
}
df1 %>%
my_impute(q1, vals = 1:2) %>%
tabyl(q1)
# q1 n percent
# 1 4285 0.857
# 2 715 0.143
补充我的两分钱,rlang 的新版本允许替换准引用过程:enquo() + !!你可以使用 curly-curly 来包含变量:函数就像:
my_impute <- function(.data, .prob_var, vals, ...) {
#.prob_var = enquo(.prob_var)
# commented out since it is no longer needed
.prob_vals <- .data %>%
janitor::tabyl({{.prob_var}}) %>%
filter({{.prob_var}} %in% {{vals}}) %>%
pull(percent)
.data %>%
mutate( {{.prob_var}} := case_when( {{.prob_var}} == 5 ~
sample(
2,
n(),
prob = {{.prob_vals}},
replace = TRUE
),
TRUE ~ as.integer(q1))
)
}
我有一个数据集,我喜欢根据这些值的概率分布来估算其中的一个值。让我们先做一些可重现的例子
library(tidyverse)
library(janitor)
dummy1 <- runif(5000, 0, 1)
dummy11 <- case_when(
dummy1 < 0.776 ~ 1,
dummy1 < 0.776 + 0.124 ~ 2,
TRUE ~ 5)
df1 <- tibble(q1 = dummy11)
这是输出:
df1 %>% tabyl(q1)
q1 n percent
1 3888 0.7776
2 605 0.1210
5 507 0.1014
我使用 mutate
和 sample
在值 1 和 2 之间共享值 = 5,如下所示:
df1 %>%
mutate(q1 = case_when(q1 == 5 ~ sample(
2,
length(q1),
prob = c(0.7776, 0.1210),
replace = TRUE
),
TRUE ~ as.integer(q1))
)
结果如下:
q1 n percent
1 4322 0.8644
2 678 0.1356
这种方法似乎可行,但是因为我需要将其应用于多个变量,所以我尝试编写一个函数来使用 tidyverse 和 tidyeval
,就像这样
my_impute <- function(.data, .prob_var, ...) {
.prob_var <- enquo(.prob_var)
.data %>%
sample(2, prob=c(!!.prob_var), replace = TRUE)
}
# running on data
df1 %>%
mutate(q1 = case_when(q1 == 5 ~ !!my_impute(q1),
TRUE ~ as.integer(q1))
)
错误是:
Error in eval_tidy(pair$lhs, env = default_env) : object 'q1' not found
我们需要 tabyl
生成的 'percent' 列中的 prob
值,因此可以将函数修改为
library(janitor)
library(dplyr)
my_impute <- function(.data, .prob_var, vals, ...) {
.prob_var = enquo(.prob_var)
.prob_vals <- .data %>%
janitor::tabyl(!!.prob_var) %>%
filter(!!.prob_var %in% vals) %>%
pull(percent)
.data %>%
mutate(!! .prob_var := case_when(!! .prob_var == 5 ~
sample(
2,
n(),
prob = .prob_vals,
replace = TRUE
),
TRUE ~ as.integer(q1))
)
}
df1 %>%
my_impute(q1, vals = 1:2) %>%
tabyl(q1)
# q1 n percent
# 1 4285 0.857
# 2 715 0.143
补充我的两分钱,rlang 的新版本允许替换准引用过程:enquo() + !!你可以使用 curly-curly 来包含变量:函数就像:
my_impute <- function(.data, .prob_var, vals, ...) {
#.prob_var = enquo(.prob_var)
# commented out since it is no longer needed
.prob_vals <- .data %>%
janitor::tabyl({{.prob_var}}) %>%
filter({{.prob_var}} %in% {{vals}}) %>%
pull(percent)
.data %>%
mutate( {{.prob_var}} := case_when( {{.prob_var}} == 5 ~
sample(
2,
n(),
prob = {{.prob_vals}},
replace = TRUE
),
TRUE ~ as.integer(q1))
)
}