我试图将一个从原始数据框创建子集的函数组合在一起,然后使用dplyr的SELECT和MUTATE根据总和给出大/小条目的数量萼片/花瓣的宽度和长度。
filter <- function (spp, LENGTH, WIDTH) {
d <- subset (iris, subset=iris$Species == spp) # This part seems to work just fine
large <- d %>%
select (LENGTH, WIDTH) %>% # This is where the problem arises.
mutate (sum = LENGTH + WIDTH)
big_samples <- which(large$sum > 4)
return (length(big_samples))
}
基本上,我希望函数返回大花的数量。但是,当我运行该函数时,我收到以下错误 -
filter("virginica", "Sepal.Length", "Sepal.Width")
Error: All select() inputs must resolve to integer column positions.
The following do not:
* LENGTH
* WIDTH
我做错了什么?
答案 0 :(得分:19)
您遇到了NSE / SE问题,请参阅the vignette for more info。
简而言之,dplyr
使用名称的非标准评估(NSE),并且将列的名称传递给函数会破坏它,而不使用标准评估(SE)版本。
dplyr
函数的SE版本以_结尾。您可以看到select_
与原始参数很好地配合使用。
然而,使用函数时事情会变得更复杂。我们可以使用lazyeval::interp
将大多数函数参数转换为列名,请参阅下面函数中mutate
到mutate_
调用的转换,更一般地说,帮助:?lazyeval::interp
尝试:
filter <- function (spp, LENGTH, WIDTH) {
d <- subset (iris, subset=iris$Species == spp)
large <- d %>%
select_(LENGTH, WIDTH) %>%
mutate_(sum = lazyeval::interp(~X + Y, X = as.name(LENGTH), Y = as.name(WIDTH)))
big_samples <- which(large$sum > 4)
return (length(big_samples))
}
答案 1 :(得分:10)
UPDATE :从dplyr 0.7.0开始,您可以使用整洁的eval来完成此任务。
有关详细信息,请参阅http://dplyr.tidyverse.org/articles/programming.html。
filter_big <- function(spp, LENGTH, WIDTH) {
LENGTH <- enquo(LENGTH) # Create quosure
WIDTH <- enquo(WIDTH) # Create quosure
iris %>%
filter(Species == spp) %>%
select(!!LENGTH, !!WIDTH) %>% # Use !! to unquote the quosure
mutate(sum = (!!LENGTH) + (!!WIDTH)) %>% # Use !! to unquote the quosure
filter(sum > 4) %>%
nrow()
}
filter_big("virginica", Sepal.Length, Sepal.Width)
> filter_big("virginica", Sepal.Length, Sepal.Width)
[1] 50
答案 2 :(得分:1)
如果对您来说,定额报价和准报价太贵了,请改用.data[[ ]]
或rlang
{{ }}
(curly curly)。有关更多信息,请参见Hadley的Advanced R书中的Hadley Wickham's 5min video on tidy evaluation和(也许)Tidy evaluation section。
library(rlang)
library(dplyr)
filter_data <- function(df, spp, LENGTH, WIDTH) {
res <- df %>%
filter(Species == spp) %>%
select(.data[[LENGTH]], .data[[WIDTH]]) %>%
mutate(sum = .data[[LENGTH]] + .data[[WIDTH]]) %>%
filter(sum > 4) %>%
nrow()
return(res)
}
filter_data(iris, "virginica", "Sepal.Length", "Sepal.Width")
#> [1] 50
filter_rlang <- function(df, spp, LENGTH, WIDTH) {
res <- df %>%
filter(Species == spp) %>%
select({{LENGTH}}, {{WIDTH}}) %>%
mutate(sum = {{LENGTH}} + {{WIDTH}}) %>%
filter(sum > 4) %>%
nrow()
return(res)
}
filter_rlang(iris, "virginica", Sepal.Length, Sepal.Width)
#> [1] 50
由reprex package(v0.3.0)于2019-11-10创建