```r
library(dplyr)
df %>%
mutate(across(col1:col2, ~ if_else(n_distinct(.x) == 1, paste(.x, collapse = ':'), NA),
.names = "match_extract_{.col}"),
match_extract_col1_2 = if_else(col1[1] == col2[2], paste(col1[1], col2[2], sep = ':'), NA),
.by = ID)
# ID col1 col2 match_extract_col1 match_extract_col2 match_extract_col1_2
# 1 AB 1 3 <NA> <NA> 1:1
# 2 AB 0 1 <NA> <NA> 1:1
# 3 CD 2 4 2:2 <NA> <NA>
# 4 CD 2 3 2:2 <NA> <NA>
```
You can use `n_distinct() == 1` to know if there is a mismatch in each column by `ID` groups.
```r
library(dplyr)
df %>%
mutate(across(col1:col2, ~ if_else(n_distinct(.x) == 1, NA, toString(.x)),
.names = "mismatch_extract_{.col}"),
.by = ID)
# # A tibble: 4 × 5
# ID col1 col2 mismatch_extract_col1 mismatch_extract_col2
# <chr> <int> <int> <lgl> <chr>
# 1 AB 1 3 NA NA
# 2 AB 1 3 NA NA
# 3 CD 2 4 NA 4, 3
# 4 CD 2 3 NA 4, 3
```