How to create multiple columns from combination of pairs of another column?

I'm trying to create multiple columns which are combinations of pairs based on another column. For example, in this reduced forcats::gss_cat dataset, there is a marital column with three values: Separated, Divorced, and Married. I'm able to create new columns like Separated_Divorced using mutate and case_when, like this:

Reduced dataset for simplicity

data <- forcats::gss_cat %>% 
  filter(marital != "No answer") %>% 
  filter(marital != "Never married") %>% 
  filter(marital != "Widowed")

data %>% count(marital)

marital           n
Separated       743         
Divorced       3383         
Married       10117 

Manually creating columns based on pairs

Separated_Divorced, Divorced_Married, Married_Separated

data <- data %>% 
  mutate(Separated_Divorced = case_when(marital == "Separated" ~ "Separated",
                                        marital == "Divorced" ~ "Divorced"),
         Divorced_Married = case_when(marital == "Divorced" ~ "Divorced",
                                      marital == "Married" ~ "Married"),
         Married_Separated = case_when(marital == "Married" ~ "Married",
                                       marital == "Separated" ~ "Separated")) 

Is there a function or a simple way to create these columns without manually creating columns unlike this approach?


Solution 1:

We may use combn on the levels of the 'marital'

library(dplyr)
library(stringr)
data2 <- combn(levels(data$marital), 2, FUN = \(x) 
   data %>%  
     transmute(!! str_c(x, collapse="_") := 
        case_when(as.character(marital) %in% x~ as.character(marital))), 
          simplify = FALSE) %>%
    bind_cols(data, .)

-output

> head(data2, 2)
# A tibble: 2 × 24
   year marital    age race  rincome        partyid relig denom tvhours `No answer_Neve… `No answer_Sepa… `No answer_Divo… `No answer_Wido… `No answer_Marr… `Never married_…
  <int> <fct>    <int> <fct> <fct>          <fct>   <fct> <fct>   <int> <chr>            <chr>            <chr>            <chr>            <chr>            <chr>           
1  2000 Divorced    48 White $8000 to 9999  Not st… Prot… Bapt…      NA <NA>             <NA>             Divorced         <NA>             <NA>             <NA>            
2  2000 Divorced    25 White Not applicable Not st… None  Not …       1 <NA>             <NA>             Divorced         <NA>             <NA>             <NA>            
# … with 9 more variables: Never married_Divorced <chr>, Never married_Widowed <chr>, Never married_Married <chr>, Separated_Divorced <chr>,
#   Separated_Widowed <chr>, Separated_Married <chr>, Divorced_Widowed <chr>, Divorced_Married <chr>, Widowed_Married <chr>