In R, creating a column of tag names that are surrounded by quotes and separated by commas

Viewed 62

In R, I am trying to create a column for a tibble that will contain a string of tags that will be used to segment an email list in MailChimp.

The format of the tags column in the output CSV that I will upload to MailChimp should be a string: "Attribute 1", "Attribute 2"

I suspect that doing this will involve creating a function with an if statement, and adding a tag based upon a TRUE/FALSE logical.

Here is what the data structure would look like:

library(tidyverse)

person <- c("Person 1", "Person 2", "Person 3", "Person 4")
is_in_A <- c(TRUE, FALSE, TRUE, FALSE)
is_in_B <-  c(TRUE, FALSE, FALSE, TRUE)
is_in_C <- c(TRUE, TRUE, TRUE, TRUE)

example_tbl <- tibble(person = person, is_in_A = is_in_A, is_in_B, is_in_C = is_in_C)

this is what the data looks like:
example_tbl

# person   is_in_A is_in_B is_in_C  
# <chr>     <lgl>   <lgl>   <lgl>   
# Person 1  TRUE    TRUE    TRUE    
# Person 2  FALSE   FALSE   TRUE    
# Person 3  TRUE    FALSE   TRUE    
# Person 4  FALSE   TRUE    TRUE    

This is what the output should look like:

tags_1 <- '"is in A", "is in B", "is in C"'
tags_2 <- '"is in C"'
tags_3 <- '"is in A", "is in C"'
tags_4 <- '"is in B", "is in C"'

all_tags <- c(tags_1, tags_2, tags_3, tags_4)

example_output_tbl <- example_tbl %>%
  add_column(tags = all_tags)

# this is what the output should look like
example_output_tbl

# person   is_in_A is_in_B is_in_C  tags
# <chr>     <lgl>   <lgl>   <lgl>   <chr>
# Person 1  TRUE    TRUE    TRUE    "is in A", "is in B", "is in C"
# Person 2  FALSE   FALSE   TRUE    "is in C"
# Person 3  TRUE    FALSE   TRUE    "is in A", "is in C"
# Person 4  FALSE   TRUE    TRUE    "is in B", "is in C"

Any suggestions would be welcome.

3 Answers

This base R could help:

example_tbl$Col <- apply(example_tbl[,-1],1,function(x) paste(names(example_tbl[,-1])[which(x==T)],collapse = ','))

# A tibble: 4 x 5
  person   is_in_A is_in_B is_in_C Col                    
  <chr>    <lgl>   <lgl>   <lgl>   <chr>                  
1 Person 1 TRUE    TRUE    TRUE    is_in_A,is_in_B,is_in_C
2 Person 2 FALSE   FALSE   TRUE    is_in_C                
3 Person 3 TRUE    FALSE   TRUE    is_in_A,is_in_C        
4 Person 4 FALSE   TRUE    TRUE    is_in_B,is_in_C  

Using rowwise with c_across :

library(dplyr)
cols <- names(example_tbl)[-1]

example_tbl %>%
  rowwise() %>%
  mutate(tags = toString(dQuote(cols[c_across(starts_with('is_in'))])))

#  person   is_in_A is_in_B is_in_C tags                           
#  <chr>    <lgl>   <lgl>   <lgl>   <chr>                          
#1 Person 1 TRUE    TRUE    TRUE    “is_in_A”, “is_in_B”, “is_in_C”
#2 Person 2 FALSE   FALSE   TRUE    “is_in_C”                      
#3 Person 3 TRUE    FALSE   TRUE    “is_in_A”, “is_in_C”           
#4 Person 4 FALSE   TRUE    TRUE    “is_in_B”, “is_in_C”           

Or pmap_chr from purrr :

example_tbl %>%
    mutate(tags = purrr::pmap_chr(select(., starts_with('is_in')), 
                  ~toString(cols[c(...)] )))  

We can reshape to 'long' format and paste the elements of 'name' after indexing with 'value' column, and join with the orignal dataset

library(dplyr)
library(tidyr)
library(stringr)
example_tbl %>%
    pivot_longer(cols = -person) %>%
    group_by(person) %>% 
    summarise(tag = str_c(dQuote(name[value], FALSE), collapse=", ")) %>% 
    left_join(example_tbl) %>%
    select(names(example_tbl), everything())
# A tibble: 4 x 5
#  person   is_in_A is_in_B is_in_C tag                                    
#  <chr>    <lgl>   <lgl>   <lgl>   <chr>                                  
#1 Person 1 TRUE    TRUE    TRUE    "\"is_in_A\", \"is_in_B\", \"is_in_C\""
#2 Person 2 FALSE   FALSE   TRUE    "\"is_in_C\""                          
#3 Person 3 TRUE    FALSE   TRUE    "\"is_in_A\", \"is_in_C\""             
#4 Person 4 FALSE   TRUE    TRUE    "\"is_in_B\", \"is_in_C\""      
Related