I would use a left join and then replace the original if it is NA.
library(dplyr)
df1 <- structure(list(id = 1:10,
group = c("a", "a", "a", "b", "b",
"c", "c", "c", "d", "d"),
var1 = c(NA, NA, NA, NA, NA, 58L,
NA, 23L, NA, 30L),
var2 = c(NA, NA, NA, NA, NA, 84L,
NA, 89L, NA, 91L),
var3 = c("O", "X", "H", "S", "T",
"E", "U", "L", "I", "B"),
var4 = c("t", "v", "u", "p", "s",
"m", "k", "f", "e", "g")),
row.names = c(NA, -10L),
class = c("tbl_df", "tbl", "data.frame"))
df2 <- structure(list(id = 1:5,
group = c("a", "a", "a", "b", "b"),
var1 = c(2L, 8L, 46L, 14L, 92L),
var2 = c(18L, 15L, 2L, 63L, 28L)),
row.names = c(NA, -5L),
class = c("tbl_df", "tbl", "data.frame"))
df3 <- structure(list(id = 1:10,
group = c("a", "a", "a", "b", "b",
"c", "c", "c", "d", "d"),
var1 = c(2L, 8L, 46L, 14L, 92L, 58L,
NA, 23L, NA, 30L),
var2 = c(18L, 15L, 2L, 63L, 28L, 84L,
NA, 89L, NA, 91L),
var3 = c("O", "X", "H", "S", "T",
"E", "U", "L", "I", "B"),
var4 = c("t", "v", "u", "p", "s",
"m", "k", "f", "e", "g")),
row.names = c(NA, -10L),
class = c("tbl_df", "tbl", "data.frame"))
df3_candidate <- left_join(df1, df2, by = "id") #notice .x and .y suffixes!
df3_candidate <- df3_candidate %>% mutate(var1 = ifelse(is.na(var1.x), var1.y, var1.x),
var2 = ifelse(is.na(var2.x), var2.y, var2.x)) %>%
select(id, group = group.x, var1, var2, var3, var4)
df3_candidate
#> # A tibble: 10 x 6
#> id group var1 var2 var3 var4
#> <int> <chr> <int> <int> <chr> <chr>
#> 1 1 a 2 18 O t
#> 2 2 a 8 15 X v
#> 3 3 a 46 2 H u
#> 4 4 b 14 63 S p
#> 5 5 b 92 28 T s
#> 6 6 c 58 84 E m
#> 7 7 c NA NA U k
#> 8 8 c 23 89 L f
#> 9 9 d NA NA I e
#> 10 10 d 30 91 B g
df3
#> # A tibble: 10 x 6
#> id group var1 var2 var3 var4
#> <int> <chr> <int> <int> <chr> <chr>
#> 1 1 a 2 18 O t
#> 2 2 a 8 15 X v
#> 3 3 a 46 2 H u
#> 4 4 b 14 63 S p
#> 5 5 b 92 28 T s
#> 6 6 c 58 84 E m
#> 7 7 c NA NA U k
#> 8 8 c 23 89 L f
#> 9 9 d NA NA I e
#> 10 10 d 30 91 B g
Created on 2019-09-12 by the reprex package (v0.2.1)