4

I would like to replace NAs in the columns that begin with v with the values in column x using current dplyr (1.0.2) code.

The same question is posted here, but the answer is outdated.

I have no trouble with one column:

suppressMessages(library(dplyr))
df <- data.frame(v1 = c(NA, 1, 2), v2 = c(3, NA, 4), v3 = c(5, 6, NA), x = c(7, 8, 9))
df %>% mutate(v1 = coalesce(v1, x))
#>   v1 v2 v3 x
#> 1  7  3  5 7
#> 2  1 NA  6 8
#> 3  2  4 NA 9

Created on 2020-11-03 by the reprex package (v0.3.0)

but can't figure out how to get it to work across multiple columns.

Here are a few things I've tried to no avail:

suppressMessages(library(dplyr))
df <- data.frame(v1 = c(NA, 1, 2), v2 = c(3, NA, 4), v3 = c(5, 6, NA), x = c(7, 8, 9))
df %>% mutate(across(starts_with("v")), . = coalesce(., x))
#> Error in list2(...): object 'x' not found

Created on 2020-11-03 by the reprex package (v0.3.0)

suppressMessages(library(dplyr))
df <- data.frame(v1 = c(NA, 1, 2), v2 = c(3, NA, 4), v3 = c(5, 6, NA), x = c(7, 8, 9))
df %>% mutate(across(starts_with("v")), . = coalesce(., df$x))
#> Error: Can't combine `..1` <data.frame> and `..2` <double>.

Created on 2020-11-03 by the reprex package (v0.3.0)

Appreciate your help.

1 Answer 1

7

You were very close with across(). The approach you want is:

df %>%
  mutate(across(starts_with("v"), coalesce, x))

Notice that the coalesce goes inside the across(), and that x (the second argument to coalesce() can be provided as a third argument. Result:

  v1 v2 v3 x
1  7  3  5 7
2  1  8  6 8
3  2  4  9 9

If you prefer something closer to your approach with coalesce(., x), you can also pass that as an anonymous function with a ~:

df %>%
  mutate(across(starts_with("v"), ~ coalesce(., x)))

In other situations, this can be more flexible (for instance, if . is not the first argument to the function).

Sign up to request clarification or add additional context in comments.

2 Comments

Aha! I tried the anonymous function approach but with the ) in the wrong place--no wonder I could never get across() to work. Any thoughts on . vs .x in the anonymous function?
@jtr13 I use . when I have only one argument, but it doesn’t make a difference and I don’t have an opinion. (Though .x might make it more immediately obvious that it’s not referring to the object passed into the pipe)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.