Более простой вариант - генерировать новые столбцы в функции только путем замены transmute
на mutate
, итерации и объединения их во фрейм данных с map_dfc
, а затем с помощью bind_cols
, чтобы добавить их вoriginal:
library(tidyverse)
func <- function(x) {
a <- sym(paste0("Sepal.", x)) # these need to be quosures to refer to variables
b <- sym(paste0("Petal.", x))
iris %>% transmute(
!!paste0("Compare.", x) := case_when(
!!a > !!b ~ "Sepal", # unquote quosures
!!a < !!b ~ "Petal",
TRUE ~ "Equal"
)
)
}
inputVector <- c("Length", "Width")
iris %>% bind_cols(map_dfc(inputVector, func)) %>% head()
#> Sepal.Length Sepal.Width Petal.Length Petal.Width Species Compare.Length
#> 1 5.1 3.5 1.4 0.2 setosa Sepal
#> 2 4.9 3.0 1.4 0.2 setosa Sepal
#> 3 4.7 3.2 1.3 0.2 setosa Sepal
#> 4 4.6 3.1 1.5 0.2 setosa Sepal
#> 5 5.0 3.6 1.4 0.2 setosa Sepal
#> 6 5.4 3.9 1.7 0.4 setosa Sepal
#> Compare.Width
#> 1 Sepal
#> 2 Sepal
#> 3 Sepal
#> 4 Sepal
#> 5 Sepal
#> 6 Sepal
Несколько более элегантный подход состоит в том, чтобы структурировать функцию так, чтобы она взяла вектор, переместив всю итерацию внутрь.Вы можете использовать описанный выше подход или просто сгенерировать векторы и собрать их во фрейм данных, если их несколько:
func2 <- function(x) {
columns <- map_dfc(x, function(y){
a <- paste0("Sepal.", y)
b <- paste0("Petal.", y)
column <- list(case_when(
iris[[a]] > iris[[b]] ~ "Sepal", # base notation is simpler than quosures
iris[[a]] < iris[[b]] ~ "Petal",
TRUE ~ "Equal"
))
names(column) <- paste0("Compare.", y)
column
})
iris %>% bind_cols(columns)
}
func2(inputVector) %>% tail()
#> Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#> 145 6.7 3.3 5.7 2.5 virginica
#> 146 6.7 3.0 5.2 2.3 virginica
#> 147 6.3 2.5 5.0 1.9 virginica
#> 148 6.5 3.0 5.2 2.0 virginica
#> 149 6.2 3.4 5.4 2.3 virginica
#> 150 5.9 3.0 5.1 1.8 virginica
#> Compare.Length Compare.Width
#> 145 Sepal Sepal
#> 146 Sepal Sepal
#> 147 Sepal Sepal
#> 148 Sepal Sepal
#> 149 Sepal Sepal
#> 150 Sepal Sepal