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