r语言 - 使用列表作为突变内部case_when的输入



简而言之: 您可以使用!!!拼接和列表输入来mutate内部case_when,以及如何?

如 dplyr>0.7.0 上一个问题的回答中所述,您可以在case_when()内使用裸变量名称mutate()

接下来,在case_when的帮助文件中,它显示了如何使用模式列表和!!!如下: (模式是错误的方式,首先是一般情况,但这是实际文档中的情况,对我的问题无关紧要)

x <- 1:50
patterns <- list(
TRUE ~ as.character(x),
x %%  5 == 0 ~ "fizz",
x %%  7 == 0 ~ "buzz",
x %% 35 == 0 ~ "fizz buzz"
)
case_when(!!! patterns)

但是,结合使用这些方法似乎不起作用:

testframe <- tibble(y = 1:50) #Switching to y so the x from earlier can't interfere
testframe2 <- testframe %>% 
mutate(
fizzbuzz = case_when(
y %% 35 == 0 ~ "fizz buzz",
y %% 5 == 0 ~ "fizz",
y %% 7 == 0 ~ "buzz",
TRUE ~ as.character(y)
)
)
patterns <- list(
y %% 35 == 0 ~ "fizz buzz",
y %% 5 == 0 ~ "fizz",
y %% 7 == 0 ~ "buzz",
TRUE ~ as.character(y)
)
testframe3 <- testframe %>% 
mutate(
fizzbuzz = case_when(
!!!(patterns)
)
)

testframe2 可以正常工作,而 testframe3 给出以下错误:

Error in mutate_impl(.data, dots) : 
Evaluation error: object 'y' not found.

我假设这里有一些 NSE 魔法在起作用,但我还没有设法quo()摆脱困境。我确实查看了testframe2和3的quo()(使用dplyr小插图编程时建议的调试方法)。我注意到它们是相同的:

testframe2quo <- quo(testframe %>% 
mutate(
fizzbuzz = case_when(
y %% 35 == 0 ~ "fizz buzz",
y %% 5 == 0 ~ "fizz",
y %% 7 == 0 ~ "buzz",
TRUE ~ as.character(y)
)
)
)
testframe3quo <- quo(testframe %>% 
mutate(
fizzbuzz = case_when(
!!!(patterns)
)
)
)
testframe2quo
<quosure: global>
~testframe %>% mutate(fizzbuzz = case_when(y%%35 == 0 ~ "fizz buzz", 
y%%5 == 0 ~ "fizz", y%%7 == 0 ~ "buzz", TRUE ~ as.character(y)))
testframe3quo
<quosure: global>
~testframe %>% mutate(fizzbuzz = case_when(y%%35 == 0 ~ "fizz buzz", 
y%%5 == 0 ~ "fizz", y%%7 == 0 ~ "buzz", TRUE ~ as.character(y)))

所有这些都让我回到了我的问题: 您可以使用!!!拼接和列表输入来case_whenmutate内部,以及如何?

您应该将案例包装在exprs而不是list中,并使用前缀.data

patterns <- rlang::exprs(
.data$y %% 35 == 0 ~ "fizz buzz",
.data$y %% 5 == 0 ~ "fizz",
.data$y %% 7 == 0 ~ "buzz",
TRUE ~ as.character(.data$y)
)
mutate(testframe, fizzbuzz = case_when(!!! patterns))

最新更新