One possibility is to work with both dataframes in long format. Here, I pivot df1 long, then I left_join to df2 (also after converting it to a long format). For dates that have a match, the name from df2 will be present (while others will be NA), then we can use this information to convert the date data to NA if there is no match. Then, I drop the column name.y that had the visit number, and keep only unique values. Then, we can pivot back to the wider format.
library(tidyverse)
df1 %>%
mutate(row = row_number()) %>%
pivot_longer(-row) %>%
left_join(.,
df2 %>% mutate(row = row_number()) %>%
pivot_longer(-row),
by = c("row", "value")) %>%
mutate(value = case_when(is.na(name.y)
~ as.Date(NA),
TRUE ~ value)) %>%
select(-name.y) %>%
distinct() %>%
pivot_wider(names_from = "name.x", values_from = "value") %>%
select(-row)
Output
MEASUREDATE1 MEASUREDATE2 MEASUREDATE3 MEASUREDATE4 MEASUREDATE5 MEASUREDATE6 MEASUREDATE7 MEASUREDATE8 MEASUREDATE9 MEASUREDATE10
<date> <date> <date> <date> <date> <date> <date> <date> <date> <date>
1 NA 2018-05-09 2018-06-16 2018-07-06 2018-09-27 2018-10-04 2018-10-26 NA NA NA
2 NA NA NA 2018-11-12 2018-12-30 2019-01-03 NA NA NA NA
3 2019-08-28 2020-03-15 NA NA NA NA NA NA NA NA
Update
If you want to distinguish between FALSE and NA, then we will need to convert date to character first. Then, we can set some additional conditions in case_when.
df1 %>%
mutate(row = row_number()) %>%
pivot_longer(-row) %>%
left_join(.,
df2 %>% mutate(row = row_number()) %>%
pivot_longer(-row),
by = c("row", "value")) %>%
mutate(across(everything(), ~as.character(.))) %>%
mutate(value = case_when(is.na(name.y) & !is.na(value) ~ "FALSE",
!is.na(name.y) & !is.na(value) ~ value,
TRUE ~ "NA")) %>%
select(-name.y) %>%
distinct() %>%
pivot_wider(names_from = "name.x", values_from = "value") %>%
select(-row)
Output
MEASUREDATE1 MEASUREDATE2 MEASUREDATE3 MEASUREDATE4 MEASUREDATE5 MEASUREDATE6 MEASUREDATE7 MEASUREDATE8 MEASUREDATE9 MEASUREDATE10
<chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 FALSE 2018-05-09 2018-06-16 2018-07-06 2018-09-27 2018-10-04 2018-10-26 FALSE FALSE FALSE
2 FALSE FALSE FALSE 2018-11-12 2018-12-30 2019-01-03 FALSE FALSE NA NA
3 2019-08-28 2020-03-15 FALSE FALSE FALSE FALSE NA NA NA NA
Data
df1 <- structure(
list(
MEASUREDATE1 = structure(c(17616, 17719, 18136), class = "Date"),
MEASUREDATE2 = structure(c(17660, 17761, 18336), class = "Date"),
MEASUREDATE3 = structure(c(17698, 17787, 18337), class = "Date"),
MEASUREDATE4 = structure(c(17718, 17847, 18373), class = "Date"),
MEASUREDATE5 = structure(c(17801, 17895, 18387), class = "Date"),
MEASUREDATE6 = structure(c(17808, 17899, 18409), class = "Date"),
MEASUREDATE7 = structure(c(17830, 17945, NA), class = "Date"),
MEASUREDATE8 = structure(c(17838, 18011, NA), class = "Date"),
MEASUREDATE9 = structure(c(17855, NA, NA), class = "Date"),
MEASUREDATE10 = structure(c(17861, NA, NA), class = "Date")
),
class = "data.frame",
row.names = c(NA,-3L)
)
df2 <-
structure(
list(
VISIT1 = structure(c(17660, 17847, 18136), class = "Date"),
VISIT2 = structure(c(17698, 17895, 18336), class = "Date"),
VISIT3 = structure(c(17718, 17899, NA), class = "Date"),
VISIT4 = structure(c(17801, NA, NA), class = "Date"),
VISIT5 = structure(c(17808, NA, NA), class = "Date"),
VISIT6 = structure(c(17830, NA, NA), class = "Date")
),
class = "data.frame",
row.names = c(NA,-3L)
)