Be aware of your evaluation context!

Just wanted to share a NAAASTY bug, nothing new, but perhaps a good reminder


df <- structure(list(ID = 8833857L, Date = structure(17670, class = "Date"), 
               Project = "Boom"), class = "data.frame", row.names = c(NA,-1L))

ID <- c(8833666L, 8833667L, 8833668L, 8833669L, 8833670L, 8833857L)

df %>% filter(ID == 8833857) %>% pull(ID)
[1] 8833857
## ^ expected

df %>% filter(ID == ID[6]) %>% pull(ID)
[1] integer(0)
## ^ What is happening???

ID[6] == 8833857
[1] TRUE

How is this possible? Try to figure it out! To see the answer, click on the spoiler tag below!!

## Column name is the same as the vector, ie, ID means two things... so it's unpredictable! 
## Solution? Just change the name of the vector so there's no clash!

IDs <- c(8833666L, 8833667L, 8833668L, 8833669L, 8833670L, 8833857L)

df %>% filter(ID == IDs[6]) %>% pull(ID)
[1] 8833857
## ^ Whew!!
3 Likes

tidyeval with !! (bang bang) can be handy here:

library(dplyr)

df <- structure(list(ID = 8833857L, Date = structure(17670, class = "Date"), 
                     Project = "Boom"), class = "data.frame", row.names = c(NA,-1L))
ID <- c(8833666L, 8833667L, 8833668L, 8833669L, 8833670L, 8833857L)
df %>% filter(ID == 8833857) %>% pull(ID)
#> [1] 8833857
df %>% filter(ID == !!ID[6]) %>% pull(ID)
#> [1] 8833857

Created on 2018-06-01 by the reprex package (v0.1.1.9000).

8 Likes

In addition to using more explicit variable names, it can also sometimes help to use the .data pronoun to clarify intent.

df %>% filter(.data$ID == ids[6])
10 Likes

didn't know about the data pronoun!! Thanks! I'll keep that one in the back of my mind

I just came back to this... I hadn't fully understood your solution... so it turns out you can !! to exit this evaluation context, even without the quo or enquo... that's how you specify "NOT FROM THIS DATAFRAME". This is genius and super useful. Thanks for this!

1 Like