我试图在编程方式中使用dplyr:使用带引号的变量进行过滤行为是不可理解的。
在多次尝试分析实际数据后,我创建了以下虚拟数据。
dt <- data.frame(
sex = rep(c("F","M"), 50),
height = runif(100, 1, 1000),
weight = rep(c(2, 100), 50),
value = runif(100, 1, 1000 ),
stringsAsFactors = FALSE
)
library(dplyr)
wizard_fun_1 <- function(param1){
par1 <- enquo(param1)
dt %>% select(height, !!par1)
}
wizard_fun_1("sex")
# as expected
#1 74.875344 F
#2 846.614856 M
#.....
wizard_fun_2 <- function(param1){
par1 <- enquo(param1)
dt %>% select(height, !!par1) %>%
filter( (!!par1) == 'M')
}
wizard_fun_2('sex')
#[1] height sex
# ... zero rows....
出了什么问题? 感谢先进的任何想法!
答案 0 :(得分:1)
如果您使用enquo
,则应该在没有引号的情况下调用您的函数。例如
wizard_fun_2(sex)
工作得很好。 select
函数可以使用字符串或符号。这两个都可行
select(dt, sex) # more common
select(dt, "sex")
但filter()
filter(sex=="M")
filter("sex"=="M")
在字符串和不带引号的符号/名称之间跳转时要小心。当您使用引用标记时,您根本就没有使用非标准评估。
答案 1 :(得分:1)
在您使用enquo
的函数中,但是当您调用该函数时,您将列名称作为字符串而不是裸名称传递。你只需要在调用函数时使用裸列名称,它就像写的那样工作。
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
dt <- tibble(
sex = rep(c("F","M"), 50),
height = runif(100, 1, 1000),
weight = rep(c(2, 100), 50),
value = runif(100, 1, 1000 )
)
wizard_fun_2 <- function(param1){
par1 <- enquo(param1)
dt %>% select(height, !!par1) %>%
filter( (!!par1) == "M")
}
wizard_fun_2(sex)
#> # A tibble: 50 x 2
#> height sex
#> <dbl> <chr>
#> 1 871.7788 M
#> 2 467.9220 M
#> 3 272.6478 M
#> 4 445.1101 M
#> 5 682.2095 M
#> 6 831.8522 M
#> 7 727.9525 M
#> 8 203.7829 M
#> 9 742.3000 M
#> 10 322.0473 M
#> # ... with 40 more rows