From my point of view, this seems like a fairly easy thing to do, but I'm having such trouble trying to get this to work.
What I'm trying to do, via mutate()
and across()
, is simply to make some variables just evaluate to a constant or a scalar within a custom function.
I'll demonstrate this with a non-across()
implementation:
library(dplyr, warn.conflicts = FALSE)
vars <- c("mpg", "cyl")
Test_Function <- function(.data, .vars) {
Data_Frame <- .data %>%
mutate(
!!.vars[1] := "Something",
!!.vars[2] := 2L
) %>%
select({{.vars}}) %>%
as_tibble()
return(Data_Frame)
}
mtcars %>% Test_Function(vars)
#> # A tibble: 32 x 2
#> mpg cyl
#> <chr> <int>
#> 1 Something 2
#> 2 Something 2
#> 3 Something 2
#> 4 Something 2
#> 5 Something 2
#> 6 Something 2
#> 7 Something 2
#> 8 Something 2
#> 9 Something 2
#> 10 Something 2
#> # ... with 22 more rows
Created on 2021-08-11 by the reprex package (v2.0.1)
When I try to get the same thing accomplished via across()
, I can't get it to work:
library(dplyr, warn.conflicts = FALSE)
vars <- c("mpg", "cyl")
Test_Function <- function(.data, .vars) {
Data_Frame <-
.data %>%
mutate(
across(!!.vars, "Something"), # Doesn't work
across(!!.vars, ~ .x := "Something"), # purrr-style doesn't work
across(!!.vars, ~ assign(.x, "Something")), # purrr-style with assign() doesn't work
across(!!.vars, assign, "Something") # Regular assign() doesn't work
) %>%
select({{.vars}}) %>%
as_tibble()
return(Data_Frame)
}
mtcars %>% Test_Function(vars)
As an aside, I wish I could provide across()
some variables that don't exist in .data
so I can easily create new columns without having to do it manually inside of mutate()
, but as of the time of writing that doesn't work (yet?).
EDIT:
@MrFlick/@JonSpring,and @TimTeaFan gave suggestions that worked for me; the former for just one value, the latter for a list of values. I'll provide minimal reprexes for both of what I went with. Thanks everyone for the help!
@MrFlick/@JonSpring's suggestion, returning a single value:
library(dplyr, warn.conflicts = FALSE)
vars <- c("mpg", "cyl")
Test_Function <- function(.data, .vars) {
Data_Frame <-
.data %>%
mutate(
across(!!.vars, ~ "Something"), # I was so close to this initially, I just missed the tilde.
) %>%
select({{.vars}}) %>%
as_tibble()
return(Data_Frame)
}
mtcars %>% Test_Function(vars)
#> # A tibble: 32 x 2
#> mpg cyl
#> <chr> <chr>
#> 1 Something Something
#> 2 Something Something
#> 3 Something Something
#> 4 Something Something
#> 5 Something Something
#> 6 Something Something
#> 7 Something Something
#> 8 Something Something
#> 9 Something Something
#> 10 Something Something
#> # ... with 22 more rows
Created on 2021-08-12 by the reprex package (v2.0.1)
And now @TimTeaFan's suggestion:
library(dplyr, warn.conflicts = FALSE)
varlist <-
list(
"mpg" = "Something",
"cyl" = 2L
)
vars <- c("mpg", "cyl")
Test_Function <- function(.data, .varlist, .vars) {
Data_Frame <-
.data %>%
mutate(
!!! .varlist # I haven't really undstood the big-bang operator (!!!) before now, so this was a great demonstration!
) %>%
select(!!.vars) %>%
as_tibble()
return(Data_Frame)
}
mtcars %>% Test_Function(varlist, vars)
#> # A tibble: 32 x 2
#> mpg cyl
#> <chr> <int>
#> 1 Something 2
#> 2 Something 2
#> 3 Something 2
#> 4 Something 2
#> 5 Something 2
#> 6 Something 2
#> 7 Something 2
#> 8 Something 2
#> 9 Something 2
#> 10 Something 2
#> # ... with 22 more rows
Created on 2021-08-12 by the reprex package (v2.0.1)
across()
. Do you just want all the columns to be "Something"? You still need to use:=
for new variable names.across()
can't help you with that. – MrFlickacross()
would add here. Doesmutate(across(!!.vars, ~paste("Something")))
do what you want? – Jon Springpaste()
, right? Justmutate(across(!!.vars, ~"Something"))
– MrFlick