Reputation: 984
I'd like to use the map_chr function on a dataset like so
library(purrr)
library(dplyr)
f <- function(x) if(x == "a") NULL else "blah"
f("a") # returns NULL
# make tibble
mytib <- tibble(test = c("a", "b"))
# naive map_chr
mytib %>% mutate(getf = map_chr(test, f))
# with .default
mytib %>% mutate(getf = map_chr(test, f, .default = NA_character_))
As you can see, map_chr fails with error message Error: Problem with `mutate()` input `getf`. x unused argument (.default = NA)
.
Attempts with possibly and na_if as described elsewhere didn't work for me either.
How can I get map_chr to loop over the arguments and leave NULL values to be NA_character_ or some other value?
Upvotes: 1
Views: 1993
Reputation: 133
purrr::map_chr()
will try to convert the list output to a character
vector, if you try to convert a NULL
object to a character you get something like this:
as.character(NULL)
#> character(0)
Which is a vector with length 0. Moreover, NULL is not valid object type for this function. By the other hand, this is what you get if try to convert a NA_character_
to character.
.
as.character(NA_character_)
#> NA
You can try this:
library(purrr)
f <- function(x) if(x == "a") NA_character_ else "blah"
# make tibble
mytib <- tibble(test = c("a", "b"))
# naive map_chr
mytib %>% mutate(getf = map_chr(test, f))
## A tibble: 2 x 2
# test getf
# <chr> <chr>
#1 a NA
#2 b blah
Upvotes: 0
Reputation: 887511
It may be better to define the f
to return NA_character_
f <- function(x) if(x == "a") NA_character_ else "blah"
and then the OP's call works as expected
Or instead of looping, create a vectorized function
f <- function(x) case_when(x != 'a' ~ 'blah')
and then call as
mytib %>%
mutate(getf = f(test))
Or another option if the f
is already defined to return NULL
, then concatenate with NA
and extract the first element. NULL
doesn't have any length
, so concatenating with NA
returns NA
only
c(NULL, NA_character_)
#[1] NA
mytib %>%
mutate(getf = map_chr(test, ~ c(f(.x), NA_character_)[1]))
# A tibble: 2 x 2
# test getf
# <chr> <chr>
#1 a <NA>
#2 b blah
The [1]
index is to extract those cases where there is actual values 'blah' returns, so that we select only the first element i.e. 'blah' and for those with if
condition is TRUE
, it will anyway return only NA_character_
Upvotes: 1