Reputation: 1484
Am trying to use mutate function inside my own created function to in order to deal with DRY principle. Am not sure if it would be possible. Whenever I run the function collapsevars
I get the correct answer but the mutate function does not pick the variable name specified in the collapsevars
function. Any leads?
The sample code is as below:
library(dplyr)
set.seed(2021)
avars <- c("a1", "a2") # Variables to collapse to a single variable
bvars <- c("b1", "b2") # Variables to collapse to another variable
mydata <- tibble(
a1 = factor(round(runif(20, 1, 3)),
labels = c("Yes", "No", "N/A")),
a2 = factor(round(runif(20, 1, 3)),
labels = c("Yes", "No", "N/A")),
b1 = factor(round(runif(20, 1, 3)),
labels = c("Yes", "No", "N/A")),
b2 = factor(round(runif(20, 1, 3)),
labels = c("Yes", "No", "N/A")),
c1 = round(rnorm(20, 10, 2)))
mydata
mydata <- mydata %>%
mutate(afin = ifelse(rowSums(
select(., all_of(avars)) == "Yes") > 0,
"Yes", "No"),
bfin = ifelse(rowSums(
select(., all_of(bvars)) == "Yes") > 0,
"Yes", "No"))
collapsevars <- function(var, varcollapse){
mydata <- mydata %>%
mutate(var = ifelse(rowSums(
select(., all_of(varcollapse)) == "Yes") > 0,
"Yes", "No"))
}
collapsevars(afin, avars)
Upvotes: 3
Views: 166
Reputation: 887831
Using case_when
library(dplyr)
collapsevars <- function(var, varcollapse){
mydata %>%
mutate({{var}} := case_when(rowSums(
select(., all_of(varcollapse)) == "Yes") > 0 ~
"Yes", TRUE ~ "No"))
}
collapsevars(afin, avars)
Upvotes: 2
Reputation: 21938
You can also use the following solution. We use unquo
or ensym
function here to unquote a user-defined argument and then we use bang-bang !!
operator on the LHS
of :=
to force-evaluate it:
library(rlang)
collapsevars <- function(var, varcollapse){
var <- enquo(var)
mydata <- mydata %>%
mutate(!!var := ifelse(rowSums(
select(., all_of(varcollapse)) == "Yes") > 0,
"Yes", "No"))
mydata
}
collapsevars(afin, avars)
# A tibble: 20 x 7
a1 a2 b1 b2 c1 afin bfin
<fct> <fct> <fct> <fct> <dbl> <chr> <chr>
1 No Yes Yes Yes 10 Yes Yes
2 N/A N/A N/A No 14 No No
3 No No No Yes 9 No Yes
4 No No N/A No 14 No No
5 No No Yes N/A 10 No Yes
6 No N/A N/A Yes 8 No Yes
7 No N/A N/A Yes 13 No Yes
8 No N/A Yes No 9 No Yes
9 N/A N/A Yes No 11 No Yes
10 N/A N/A N/A Yes 11 No Yes
11 Yes Yes No Yes 9 Yes Yes
12 N/A N/A No No 5 No No
13 No N/A Yes Yes 10 No Yes
14 No N/A No N/A 9 No No
15 N/A No No Yes 8 No Yes
16 No Yes Yes No 10 Yes Yes
17 No N/A No No 11 No No
18 N/A Yes No No 10 Yes No
19 N/A N/A N/A No 7 No No
20 No No N/A N/A 7 No No
Upvotes: 3
Reputation: 389235
You can use {{col}} :=
on left hand side in mutate
-
library(dplyr)
collapsevars <- function(var, varcollapse){
mydata <- mydata %>%
mutate({{var}} := ifelse(rowSums(
select(., all_of(varcollapse)) == "Yes") > 0,
"Yes", "No"))
mydata
}
collapsevars(afin, avars)
# A tibble: 20 x 6
# a1 a2 b1 b2 c1 afin
# <fct> <fct> <fct> <fct> <dbl> <chr>
# 1 No Yes Yes Yes 10 Yes
# 2 N/A N/A N/A No 14 No
# 3 No No No Yes 9 No
# 4 No No N/A No 14 No
# 5 No No Yes N/A 10 No
# 6 No N/A N/A Yes 8 No
# 7 No N/A N/A Yes 13 No
# 8 No N/A Yes No 9 No
# 9 N/A N/A Yes No 11 No
#10 N/A N/A N/A Yes 11 No
#11 Yes Yes No Yes 9 Yes
#12 N/A N/A No No 5 No
#13 No N/A Yes Yes 10 No
#14 No N/A No N/A 9 No
#15 N/A No No Yes 8 No
#16 No Yes Yes No 10 Yes
#17 No N/A No No 11 No
#18 N/A Yes No No 10 Yes
#19 N/A N/A N/A No 7 No
Upvotes: 1