When trying to filter a column using quo_name
, filter is not working as expected. Please see below reprex using dplyr 0.7.4
set.seed(1000)
df <- data.frame(x = sample(100,100,T), y = sample(letters,100,T), z = sample(c("One","Two","Three"),100,T))
func <- function(letter){
letter <- enquo(letter)
df %>%
group_by(z) %>%
summarise(!!quo_name(letter) := sum(x)) %>%
filter(!!quo_name(letter) < 1600)
}
func(a)
# A tibble: 3 x 2
z a
<fctr> <int>
1 One 1412
2 Three 1614
3 Two 1808
Expected output:
# A tibble: 2 x 2
z a
<fctr> <int>
1 One 1412
If I filter outside of the function, the output is the expected: func(a) %>% filter(a < 1600)
This works
library(dplyr, warn.conflicts = F)
set.seed(1000)
df <- data.frame(x = sample(100,100,T), y = sample(letters,100,T), z = sample(c("One","Two","Three"),100,T))
func <- function(letter){
letter <- enquo(letter)
df %>%
group_by(z) %>%
summarise(!! quo_name(letter) := sum(x)) %>%
filter((!! letter) < 1600)
}
func(a)
#> # A tibble: 1 x 2
#> z a
#> <fctr> <int>
#> 1 One 1412
Per Programming with dplyr vignettes, in filter
do not use quo_name
. quo_name
is useful with :=
operator because LHS expect a string or a symbol.
It is why I think this is not the issue.
Don't know why but it seems you need parenthesis in filter((!! letter) < 1600)
. filter(!!letter < 1600)
does not seems to work. Again, it is used in the vignette so it seems correct.
Hopes it helps !
@cderv You have it: it is all about operator precedence. !!a := b
parses as "assign b to !!a", !!a < b
parses as "Apply !! to (a(!!a) < b parses to "(apply !! to a) < b" (the intended effect). Roughly "!!" binds late (doesn't aggressively grab the nearest term), and :=
and <
don't have the same expression operator parsing precedence (so expressions with them to not parse the same).
H cderv,
Thank you for the clarification! That indeed works as expected. I followed the vignette, but obviously I misread that part.
Kind regards,
Most helpful comment
This works
Per Programming with dplyr vignettes, in
filter
do not usequo_name
.quo_name
is useful with:=
operator because LHS expect a string or a symbol.It is why I think this is not the issue.
Don't know why but it seems you need parenthesis in
filter((!! letter) < 1600)
.filter(!!letter < 1600)
does not seems to work. Again, it is used in the vignette so it seems correct.Hopes it helps !