Function foo
below recodes the numeric column var1
into a string column (1 -->
"a"
, 2 -->
"b"
etc.).
I was wondering how to vectorize this function such that instead of argument var1
we have argument ...
?
That is, all variables provided in ...
should undergo what var1
undergoes in foo
.
A possible useful post might be HERE.
library(tidyverse)
foo <- function(data, var1, caps = FALSE, reverse = FALSE){
let <- if(caps) base::LETTERS else base::letters
FUN <- if(reverse) utils::tail else utils::head
data %>% mutate(var1 = factor(FUN(let, max(var1))[var1]))
}
# EXAMPLE OF USE:
(dat <- data.frame(var1 = c(2,1,3,1,4:1), id = 1:8))
foo(dat, var1, caps = T, reverse = T)
CodePudding user response:
We may use across
-
foo <- function(data, caps = FALSE, reverse = FALSE, ...){
vars <- rlang::ensyms(...)
let <- if(caps) base::LETTERS else base::letters
FUN <- if(reverse) utils::tail else utils::head
data %>% mutate(across(as.character(vars), ~factor(FUN(let, max(.))[.])))
}
dat <- data.frame(var1 = c(2,1,3,1,4:1), id = 1:8)
foo(dat, caps = T, reverse = T, var1)
# var1 id
#1 X 1
#2 W 2
#3 Y 3
#4 W 4
#5 Z 5
#6 Y 6
#7 X 7
#8 W 8
foo(dat, caps = T, reverse = T, var1, id)
# var1 id
#1 X S
#2 W T
#3 Y U
#4 W V
#5 Z W
#6 Y X
#7 X Y
#8 W Z
CodePudding user response:
The approach below should do what you are looking for. It is not as clean as my answer to the linked post in your question, but it should work as expected (now also updated with default arguments that apply to all variables):
library(tidyverse)
library(rlang)
foo <- function(data, ..., caps = FALSE, reverse = FALSE){
var_ls <- map(ensyms(..., .named = TRUE), as.character)
l_varls <- length(var_ls)
if(l_varls != length(caps)) {
caps <- rep(caps, l_varls)
}
if(l_varls != length(reverse)) {
reverse <- rep(reverse, l_varls)
}
let <- ifelse(caps, list(base::LETTERS), list(base::letters))
names(let) <- names(var_ls)
FUN <- ifelse(reverse, list(utils::tail), list(utils::head))
names(FUN) <- names(var_ls)
mutate(data,
purrr::map_dfc(var_ls,
~ factor(FUN[[.x]](let[[.x]],max(data[[.x]]))[data[[.x]]]))
)
}
# EXAMPLE OF USE:
(dat <- data.frame(var1 = c(2,1,3,1,4:1), var2 = c(8:1), id = 1:8))
#> var1 var2 id
#> 1 2 8 1
#> 2 1 7 2
#> 3 3 6 3
#> 4 1 5 4
#> 5 4 4 5
#> 6 3 3 6
#> 7 2 2 7
#> 8 1 1 8
foo(dat, var1, var2, caps = c(TRUE,FALSE), reverse = c(FALSE, TRUE))
#> var1 var2 id
#> 1 B z 1
#> 2 A y 2
#> 3 C x 3
#> 4 A w 4
#> 5 D v 5
#> 6 C u 6
#> 7 B t 7
#> 8 A s 8
foo(dat, var1, var2)
#> var1 var2 id
#> 1 b h 1
#> 2 a g 2
#> 3 c f 3
#> 4 a e 4
#> 5 d d 5
#> 6 c c 6
#> 7 b b 7
#> 8 a a 8
foo(dat, var1, var2, caps = TRUE, reverse = TRUE)
#> var1 var2 id
#> 1 X Z 1
#> 2 W Y 2
#> 3 Y X 3
#> 4 W W 4
#> 5 Z V 5
#> 6 Y U 6
#> 7 X T 7
#> 8 W S 8
Created on 2021-09-18 by the reprex package (v0.3.0)