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"]]
(ordata$x
) rather than justx
in thei=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
R: Selecting Subset Without Copying
How to Sweep Specific Columns with Dplyr
How Does One Merge Dataframes by Row Name Without Adding a "Row.Names" Column
Changing Word Template for Knitr in Rmarkdown
Passing a 'Data.Table' to C++ Functions Using 'Rcpp' And/Or 'Rcpparmadillo'
Can Lapply Not Modify Variables in a Higher Scope
Grid.Arrange Using List of Plots
What Are Productive Ways to Debug Rcpp Compiled Code Loaded in R (On Os X Mavericks)
Difference Between Installing a Package from Source and from Compiled Binary
Treat Na as Zero Only When Adding a Number
S4 Classes: Multiple Types Per Slot
Questions About Set.Seed() in R
How to Flip Rows and Columns in R
Multiply Columns in a Data Frame by a Vector