Using `.data` pronoun with `tidyverse`
We are extensively using tidyverse framework in our functions. You can find calls to dplyr’s or tidyr’s common functions in the majority of our code. Many of the functions use data-massking (see
rlang data masking). In short, it means that you use the unqouted names passed to the function’s parameters. The function looks for these names in the data frame, so when you call mutate(df, x = y) the function will look for the y named column in the df data frame first. If there is no y named column, the function will look for the y variable in the parent environment.
Now, for many reasons it might happen that the y will be present in both: the data frame column names and the parent environment variables. To avoid the ambiguity and make the code clearer, we use the .data pronoun to indicate that the argument indeed comes from a data frame. We can also use the .env pronoun to indicate that the value comes from the parent environment.
df <- data.frame(x = 1:5, y = 1:5)
y <- 11:15
yy <- 11:15
## Here the value of z will be same as y column in data frame
## not the y variable from parent environment.
df %>%
mutate(z = y)
## Since there is no yy column in the data frame
## z will take the value of yy variable from parent environment
df %>%
mutate(z = yy)
## Same code with pronouns to make it more explicit
df %>%
mutate(z = .data$y)
df %>%
mutate(z = .env$y)
Additionally, using unqoted names passed to the function parameters triggers R CMD check to throw notes on missing definitions for particular variables. In the old school way we need to register these variable names with the globalVariables(...) function. With a lot of variables, this call might get quite long, making code cluttered in consequence. Using the .data pronoun removes the need of using globalVariables().
From tidyselect 1.2.0 there were some changes in the usage of .data pronoun with selecting functions or selection context (e.g. cols in pivot_longer. Up till now we were using .data pronoun with unquoted arguments passed to select, rename and few others. From now on, it is softly deprecated, and we should pass quoted names, also using tidyselect helpers all_of and any_of. The helpers removes the ambiguity, and will always refer to parent environment variables, since there is no data-masking (see
tidiverse 1.2.0 blog post.
df <- data.frame(x = 1:5, y = 11:15, z = 21:25)
z <- "x"
## Only column x will be selected since x is the value of z variable
df %>%
select(all_of(z))
Since tidyverse developers decided that it makes more sense to use all_of() or any_of() helpers, we also should wrap the variable names in quotes when supplied directly to selecting functions:
df <- data.frame(x = 1:5, y = 11:15, z = 21:25)
sv <- c("x", "z")
df %>%
select(all_of(sv))
df %>%
select("z")