The following code is supposed to create a list, df_test_purrr
, with two dataframes. The two dataframes should contain the columns vs, vs_txt
and am, am_txt
, respectively.
As a first step, the function fn_test
takes an argument for a dataframe, dta
, and an argument for a column, col
. Using the function directly with the argument dta = df_mtcars, col = expr(vs)
creates the dataframe df_test
as expected.
# Libaries
library(dplyr)
library(purrr)
# Data
df_mtcars <- mtcars %>%
dplyr::mutate(vs_txt = dplyr::case_when(vs == 1 ~ "ABC", T ~ "XYZ"),
am_txt = dplyr::case_when(am == 1 ~ "TTT", T ~ "BBB"))
# Function for one column
fn_test <- function(dta, col) {
{{dta}} %>%
dplyr::select( {{col}}, as.name( paste0( {{col}}, "_txt") ) )
}
# Result for one column
df_test <- fn_test( dta = df_mtcars, col = expr(vs) )
# Purrr
fn_test_purrr <- function() {
purrr::pmap(list(
list(df_mtcars, df_mtcars),
list(expr(vs), expr(am))
), fn_test )
}
df_test_purrr <- fn_test_purrr()
Defining and calling the function fn_test_purrr
gives the error:
Error in `instrument_base_errors()`:
! object 'vs' not found
Caused by error:
! object 'vs' not found
Run `rlang::last_error()` to see where the error occurred.
How can I make the function work?
Please note that the function fn_test_purrr
has more than two arguments in my real-world application such that I must use purrr's pmap
(I guess).
Please check updated code which returns the list with 2 dataframes
df_mtcars <- mtcars %>%
dplyr::mutate(vs_txt = dplyr::case_when(vs == 1 ~ "ABC", T ~ "XYZ"),
am_txt = dplyr::case_when(am == 1 ~ "TTT", T ~ "BBB"))
fn_test <- function(dta, col) {
col2 <- paste0(col,'_txt')
col2 <- col2[col2!='c_txt']
if (length(col)==1){
len=1
col2 <- paste0(col,'_txt')
} else if(length(col)>1){
len <- length(col)-1
}
my.list <- list()
for(i in 1:len){
colx <- paste0({{col}})[i+1]
colx2 <- col2[i]
dat <- dta %>%
dplyr::select( {{colx}}, colx2)
my.list[[i]] <- dat
}
return(my.list)
}
# Result for one column
mylist <- fn_test( dta = df_mtcars, col = expr(c(vs,am)) )
df1 <- as.data.frame(mylist[1])
df2 <- as.data.frame(mylist[2])