Unquote the Variable Name on the Right Side of Mutate Function in Dplyr

Unquote the variable name on the right side of mutate function in dplyr

I think you have to convert the RHS string to a quosure, which you can do with sym from the rlang package. So use

mutate(dt, !!varname_t1 := lag(!!rlang::sym(varname_t0)))

Then your function will yield

lag1_mutate(df, a, 1)
# [1] "a0"
# [1] "a1"
# # A tibble: 5 x 2
# a0 a1
# <int> <int>
# 1 3 NA
# 2 4 3
# 3 1 4
# 4 5 1
# 5 2 5

(You set no seed, so my tibble values are different from yours.)

piping dplyr mutate with unknown variable name

You don't need enquo there. That's for turning a value passed as a parameter into a quosure. Instead you need to turn a string into a symbol. For that you can use as.name() or rlang::sym()

ff <- function(tt){

# find the variable name
if(any(colnames(tt)=="AD")){
vv <- quo(AD)
} else {
vv <- colnames(tt) %>% .[.!="f1"]
vv <- as.name(vv)
}

# make the mutate
tt %>% mutate(!!quo_name(vv) := as.factor(!!vv))
}

dplyr::mutate unquote RHS

Your code should work as you expect by changing the line where you define qcol to:

qcol <- as.symbol(sprintf('q%i', i))

That is, since qcol was a string, you needed to turn it into a symbol before unquoting for it to be evaluated correctly in your mutate. Also I presume the column you wanted to refer to was the q0 column you defined in your data, not a non-existent column named qval0.

Is there a way to use mutate inside of ones own function?

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

Mutate a dynamic column name with conditions using other dynamic column names

use get to retreive column value instead

library(tidyverse)

d <- mtcars %>% tibble
fld_name <- "mpg"
other_fld_name <- "cyl"

d %>% mutate(!!fld_name := ifelse(get(other_fld_name) < 5 ,NA, get(fld_name)))

#> # A tibble: 32 x 11
#> mpg cyl disp hp drat wt qsec vs am gear carb
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 21 6 160 110 3.9 2.62 16.5 0 1 4 4
#> 2 21 6 160 110 3.9 2.88 17.0 0 1 4 4
#> 3 NA 4 108 93 3.85 2.32 18.6 1 1 4 1
#> 4 21.4 6 258 110 3.08 3.22 19.4 1 0 3 1
#> 5 18.7 8 360 175 3.15 3.44 17.0 0 0 3 2
#> 6 18.1 6 225 105 2.76 3.46 20.2 1 0 3 1
#> 7 14.3 8 360 245 3.21 3.57 15.8 0 0 3 4
#> 8 NA 4 147. 62 3.69 3.19 20 1 0 4 2
#> 9 NA 4 141. 95 3.92 3.15 22.9 1 0 4 2
#> 10 19.2 6 168. 123 3.92 3.44 18.3 1 0 4 4
#> # ... with 22 more rows

Created on 2021-06-22 by the reprex package (v2.0.0)

Using quoted variables in a custom dplyr wrapper function

Maybe I don't understand the use case, but why do the columns have to be quoted when you pass them from bar() to foo()? If you unquote the input, everything works as intended:

bar <- function(df, .cols) {
.cols <- rlang::enquo(.cols)
mutate(df, foo(!!.cols)) # <--- unquote before passing to foo()
}

# Or alternatively
bar <- function(df, .cols) {mutate(df, foo( {{.cols}} ))}

myiris %>%
bar(Sepal.Length) # works

How to iteratively add to a data frame in R using a for-loop?

You were very close with your base R approach. You just needed to:

  • remove the assignment by the if. This is because in this base R approach, you're just creating a column and not returning the dataframe.
  • refer to data[["x"]] (or data$x) rather than just x in the i=1 case.

Here's a complete working example:

library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
library(stringr)

data <- data.frame(x = 10:15)

for(i in 1:3) {
x_curnt <- str_c("x_", i)
x_prior <- str_c("x_",i-1)

if(i==1){
data[[x_curnt]] <- data[["x"]] + 1
} else {
data[[x_curnt]] <- data[[x_prior]] + 1
}
}

data
#> x x_1 x_2 x_3
#> 1 10 11 12 13
#> 2 11 12 13 14
#> 3 12 13 14 15
#> 4 13 14 15 16
#> 5 14 15 16 17
#> 6 15 16 17 18

Created on 2022-09-16 by the reprex package (v2.0.1)



Related Topics



Leave a reply



Submit