Flagging a variable which contains a string from a list

Viewed 127

I am trying to make a flag which takes note of where a variable contains one of the words from a given list. I have written an example using the starwars dataset from the dplyr library.

starwars <- starwars

name_of_characters <- c("Luke", "Han", "Jabba", "Anakin")

starwars$flag <- ifelse(starwars$name %in% name_of_characters, "Flag", "")
starwars$flag_2 <- ifelse(grep(name_of_characters, starwars$name), "Flag", "")

So what i am trying to do here is to create a flag column which will identify the characters whose names contain "Luke", "Han", "Jabba" or "Anakin". Where these names exist i want my column to simply say "Flag". I'm sure there is an easier way to do this but i've not been able to find this. For reference i'd like this to be similar to the Find() function in Excel or the Contains function in SAS.

3 Answers

First paste0 your names into a regex alternation pattern:

name_of_characters_pattern <- paste0(name_of_characters, collapse = "|")

Now use greplinside ifelseto plant the "Flag":

starwars$flag <- ifelse(grepl(name_of_characters_pattern, starwars$name),"Flag","")

Similar to Chris Ruehelmann's answer. Here using stringr verbs. after filter as last row you get the FLAGrows:

library(dplyr)
library(stringr)

pattern <- str_c(as.character(name_of_characters), collapse = "|")

starwars %>% 
    mutate(flag = if_else(str_detect(name, pattern), "FLAG", NA_character_), .before = 1) %>% 
    filter(flag == "FLAG")
  flag  name                  height  mass hair_color skin_color       eye_color birth_year sex            gender    homeworld species films     vehicles  starships
  <chr> <chr>                  <int> <dbl> <chr>      <chr>            <chr>          <dbl> <chr>          <chr>     <chr>     <chr>   <list>    <list>    <list>   
1 FLAG  Luke Skywalker           172    77 blond      fair             blue            19   male           masculine Tatooine  Human   <chr [5]> <chr [2]> <chr [2]>
2 FLAG  Anakin Skywalker         188    84 blond      fair             blue            41.9 male           masculine Tatooine  Human   <chr [3]> <chr [2]> <chr [3]>
3 FLAG  Han Solo                 180    80 brown      fair             brown           29   male           masculine Corellia  Human   <chr [4]> <chr [0]> <chr [2]>
4 FLAG  Jabba Desilijic Tiure    175  1358 NA         green-tan, brown orange         600   hermaphroditic masculine Nal Hutta Hutt    <chr [3]> <chr [0]> <chr [0]>

You don't need to use ifelse with vectorized grepl function, it feels unRish. The simple solution would be to use grepl together with factor functions:

data("starwars")

pattern <- paste(c('Luke', 'Han', 'Jabba', 'Anakin'), sep = '', collapse = '|')

starwars$flag <- factor(grepl(pattern, starwars$name), labels = c('', 'Flag'))

head(starwars[, c('name', 'flag')])


# # A tibble: 6 x 2
#   name           flag  
#   <chr>          <fct> 
# 1 Luke Skywalker "Flag"
# 2 C-3PO          ""    
# 3 R2-D2          ""    
# 4 Darth Vader    ""    
# 5 Leia Organa    ""    
# 6 Owen Lars      "" 

cat(sum(starwars$flag == 'Flag'), ' out of ', nrow(starwars), ' rows.')

# 4  out of  87  rows.

starwars[starwars$flag == 'Flag', c('name', 'flag')]

#  # A tibble: 4 x 2
#   name                  flag 
#   <chr>                 <fct>
# 1 Luke Skywalker        Flag 
# 2 Anakin Skywalker      Flag 
# 3 Han Solo              Flag 
# 4 Jabba Desilijic Tiure Flag
Related