I'm trying to write a function that takes a dataframe, converts a column from chr
to dbl
, then adds 1 to a column. I also want to optionally replace certain values with NA
. Otherwise, if the relevant argument is not used, I want the function to skip the NA replacement step.
Data
library(tibble)
library(dplyr)
library(magrittr)
df <-
tibble(id = 1:10, col_of_interest = 21:30) %>%
add_row(id = 11, col_of_interest = 999) %>%
mutate(across(col_of_interest, as.character))
df
## # A tibble: 11 x 2
## id col_of_interest
## <dbl> <chr>
## 1 1 21
## 2 2 22
## 3 3 23
## 4 4 24
## 5 5 25
## 6 6 26
## 7 7 27
## 8 8 28
## 9 9 29
## 10 10 30
## 11 11 999
Writing a function
The function should:
- Take in the data.
- Convert
col_of_interest
fromchr
todbl
. - Replace
999
with NA (but only if I specified that999
should be replaced withNA
) - Add
1
tocol_of_interest
My attempt
When writing my function I was guided by two resources:
- Passing data variables into function arguments using
{{ var }}
as covered here. - The use of
if
is based on this answer.
add_one <- function(data, var, na_if_val = NULL) {
data %>%
mutate(across({{ var }}, as.numeric)) %>%
{if( is.null( {{ na_if_val }} )
) . # <--- the dot means: "return the preexisting dataframe"
else
na_if( {{ na_if_val }} )
} %>%
mutate(across({{ var }}, add, 1))
}
When I test the function on my df
object I get an error.
add_one(data = df,
var = col_of_interest,
na_if_val = "999")
Error in check_length(y, x, fmt_args("y"), glue("same as
{fmt_args(~x)}")) : argument "y" is missing, with no default
Googling this error yielded this page, stating that:
Note, however, that na_if() can only take arguments of length one.
However, incorporating only na_if( {{ na_if_val }} )
in add_one
function's pipe does work. It's the conditional evaluation combined with is.null
that causes the function to break. I don't understand why.
I solved the problem by simply specifying
x
andy
arguments ofdrop_na
.EDIT
I removed
{{ }}
aroundna_if_val
following @LionelHenry's comment.