I have the following data structure and I want to check the presence of a specific string ('^881') across the columns var1 to var4. And to write the result of the match in a new column (RESULT), or an empty result, if the string is not found.
| var1 | var2 | var3 | var4 | EXPECTED RESULT |
|---|---|---|---|---|
| 8810 | 1234 | 8810 | ||
| 1234 | 2345 | 3456 | ||
| 1234 | 8812 | 2345 | 3456 | 8812 |
I have a solution that gives me the presence of the regex-string in a 0/1-format: (Maybe there is a more concise option?!)
library(tidyverse)
df <-
tibble(
var1 = c('8810', '1234', '1234'),
var2 = c('1234', '2345', '8812'),
var3 = c('', '3456', '2345'),
var4 = c('', '', '3456')
)
# create a new column, that indicates whether the string is present in the row (1) or not (0)
df %>%
mutate(FOUND = if_else(
across( starts_with('var'),
~ str_detect(.x, '^881')
) %>%
rowSums(., na.rm=T) > 0, 1, 0))
But I need the result of the match, that is the whole string. After some puzzling, I have found the following solution, but it has a decisive drawback. It is quite slow with large datasets (10m+ cases) and about 100 variables to search. Furthermore, it seems a bit cumbersome to me.
df %>%
mutate(across(starts_with('var'),
~ str_match(.x, '(^881.+)')[,1] # gives a tibble
) %>%
mutate(across(everything(),
stringi::stri_na2empty) # replace the NAs with empty strings
) %>%
unite('RESULT', sep = "")) # make a single column
My question: Is there a more concise way to perform this data manipulation (preferably with dplyr)?