I'm learning quasiquotation and quotation with rlang. My function looks at if any forbidden_values
occur in any of the mentioned dataframe variables selectlist
, and marks a row with any positive result as 1
, else 0
.
How can I make rlang interpret non-quoted input to the argument selectlist in the function environment instead of the global environment?
As I'm supplying a list of values, why do I have to use !!
instead of !!!
?
Why can I supply the anonymous purrr formula any function with the dot-dot-dot
operator?
This function works only with variable names to selectlist in quotes " " .
selectlist <- function(df, selectlist, forbidden_values){
enquos(selectlist)
enquos(forbidden_values)
df %>% mutate(is_injured = purrr::pmap_int(select(.,!!selectlist), ~any(c(...) %in% !!forbidden_values)))
}
selectlist(expected, selectlist=c("PrimaryInjury","SecondaryInjury"),forbidden_values=c("Rust","Insect","Snow break"))
plantid year PrimaryInjury SecondaryInjury OtherInjury is_injured
1 1 1 <NA> <NA> <NA> 0
2 1 2 Insect <NA> <NA> 1
3 1 3 <NA> <NA> <NA> 0
4 2 1 <NA> <NA> <NA> 0
5 2 2 <NA> <NA> <NA> 0
6 2 3 Rust <NA> <NA> 1
7 3 1 <NA> <NA> <NA> 0
8 3 2 <NA> <NA> <NA> 0
9 3 3 <NA> <NA> <NA> 0
10 4 1 Rust <NA> <NA> 1
11 4 2 <NA> <NA> <NA> 0
12 4 3 Insect <NA> <NA> 1
13 5 1 Snow break <NA> <NA> 1
14 5 2 Rust <NA> <NA> 1
15 5 3 <NA> <NA> <NA> 0
selectlist(expected, selectlist=c(PrimaryInjury,SecondaryInjury),forbidden_values=c("Rust","Insect","Snow break"))
Error in splice(dot_call(capture_dots, frame_env = frame_env, named = named, : object 'PrimaryInjury' not found
Thank you for helping...
Example dataframe: expected
plantid <- rep(c(1,2,3,4,5), times=c(3,3,3,3,3))
year <- rep(1:3, length.out=length(plantid))
set.seed(42)
PrimaryInjury <- sample(c(NA,NA,NA,"Rust","Insect","Snow break"), 15, replace=TRUE)
SecondaryInjury <- rep(NA, length.out=length(plantid))
OtherInjury <- rep(NA, length.out=length(plantid))
expected <- data.frame(plantid,year,PrimaryInjury,SecondaryInjury, OtherInjury)
#All in selectlist must be characters.
expected$PrimaryInjury <- as.character(expected$PrimaryInjury)
expected$SecondaryInjury <- as.character(expected$SecondaryInjury)
expected$OtherInjury <- as.character(expected$OtherInjury)
dput of expected
structure(list(plantid = c(1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4,
5, 5, 5), year = c(1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L,
3L, 1L, 2L, 3L), PrimaryInjury = c(NA, "Insect", NA, NA, NA,
"Rust", NA, NA, NA, "Rust", NA, "Insect", "Snow break", "Rust",
NA), SecondaryInjury = c(NA_character_, NA_character_, NA_character_,
NA_character_, NA_character_, NA_character_, NA_character_, NA_character_,
NA_character_, NA_character_, NA_character_, NA_character_, NA_character_,
NA_character_, NA_character_), OtherInjury = c(NA_character_,
NA_character_, NA_character_, NA_character_, NA_character_, NA_character_,
NA_character_, NA_character_, NA_character_, NA_character_, NA_character_,
NA_character_, NA_character_, NA_character_, NA_character_)), row.names = c(NA,
-15L), class = "data.frame")
If it is ok to pass unquoted variables separately, we can use three dots
selectlist <- function(df, forbidden_values, ...){
df %>% mutate(is_injured = purrr::pmap_int(select(.,...),
~any(c(...) %in% forbidden_values)))
}
selectlist(expected, forbidden_values= c("Rust","Insect","Snow break"),
PrimaryInjury, SecondaryInjury)
# plantid year PrimaryInjury SecondaryInjury OtherInjury is_injured
#1 1 1 <NA> <NA> <NA> 0
#2 1 2 Insect <NA> <NA> 1
#3 1 3 <NA> <NA> <NA> 0
#4 2 1 <NA> <NA> <NA> 0
#5 2 2 <NA> <NA> <NA> 0
#6 2 3 Rust <NA> <NA> 1
#7 3 1 <NA> <NA> <NA> 0
#8 3 2 <NA> <NA> <NA> 0
#9 3 3 <NA> <NA> <NA> 0
#10 4 1 Rust <NA> <NA> 1
#11 4 2 <NA> <NA> <NA> 0
#12 4 3 Insect <NA> <NA> 1
#13 5 1 Snow break <NA> <NA> 1
#14 5 2 Rust <NA> <NA> 1
#15 5 3 <NA> <NA> <NA> 0