I have a tibble:
df = tibble(one = list('a', 'b'), two = list(c('p1', 'p2', 'p3'), NA_character_), three = list(NA_character_, c('z1', 'z2', 'z3')))
df
# A tibble: 2 x 3
one two three
<chr> <list> <list>
1 a <chr [3]> <chr [1]>
2 b <chr [1]> <chr [3]>
I would like to replace the missing values in columns two and three with the values of column one using coalesce() and then collapse each character vector (rowwise) in two and three into a single string using toString(). My expected output looks like this:
df = tibble(one = c('a', 'b'), two = list('p1, p2, p3', 'b'), three = list('a', 'z1, z2, z3'))
df
# A tibble: 2 x 3
one two three
<chr> <list> <list>
1 a <chr [1]> <chr [1]>
2 b <chr [1]> <chr [1]>
This is what I had tried initially:
df %>% mutate_at(vars(two, three), funs(coalesce(., one) %>% map(., toString)))
I know that funs() quotes its arguments but I don't understand why it doesn't work with the pipeline. The documentation also advises that funs is being deprecated but I'm not sure what to use in its place. I was wondering if someone could shed some light on why the above doesn't work since I'm not at all familiar with the inner workings of scoped verbs.
We can use map2 , use coalesce and then toString.
library(dplyr)
library(purrr)
df1 <- df %>%
mutate_at(vars(two, three), ~map2(., one, ~toString(coalesce(.x, .y))))
df1
# one two three
# <chr> <list> <list>
#1 a <chr [1]> <chr [1]>
#2 b <chr [1]> <chr [1]>
df1$two
#[[1]]
#[1] "p1, p2, p3"
#[[2]]
#[1] "b"
df1$three
#[[1]]
#[1] "a"
#[[2]]
#[1] "z1, z2, z3"
In the above example, we use lambda style expression using ~ to use it as a function and it is true funs has been deprecated and has been replaced with list() instead. The answer and comments in this question provides more insight into this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With