Match full names with reverse in R

Viewed 106

I have 2 columns in dataset, name 1 & name 2.

Column 1    |    Column 2 
John, Smith | Smith, John

How do I compare them & make a third column return TRUE if they are in reverse order as well in R

(Preferably tidyverse)

4 Answers

This is an explicit way of doing it, which is (i think) the clearest for the exact use case in the question:

library(tidyverse)

# data
dat <- tibble(col1 = "John, Smith",
              col2 = "Smith, John")
# extractor funcs
post_comma <- function(x) gsub('^.*, ', '', x)
pre_comma <- function(x) gsub(', .*$', '', x)

dat %>%
  mutate(is_same = 
          pre_comma(col1) == post_comma(col2) &&
          post_comma(col1) == pre_comma(col2)
         )

You could split the string on comma, sort them and compare them elementwise :

library(tidyverse)

df %>%
  mutate(compare = map2_lgl(str_split(Column1, ',\\s*'), 
                            str_split(Column2, ',\\s*'), 
                            ~all(sort(.x) == sort(.y))))

#      Column1     Column2 compare
#1 John, Smith Smith, John    TRUE

The same in base R can be done with Map :

df$compare <- mapply(function(x, y) all(sort(x) == sort(y)), 
                 strsplit(df$Column1, ',\\s*'), strsplit(df$Column2, ',\\s*'))

Another way you can try. Here I use fake data to illustrate

df <- data.frame(col1 = c("John, Smith", "Peter, Crouch"), col2 = c("Smith, John", "Peter, Pan"))

df$col1_new <- sapply(lapply(strsplit(df$col1, ", "), sort), paste, collapse = " ")
df$col2_new <- sapply(lapply(strsplit(df$col2, ", "), sort), paste, collapse = " ")
df <- df %>% 
      mutate(col3 = ifelse(col1_new == col2_new, TRUE, FALSE))
#           col1        col2     col1_new     col2_new    col3
# 1   John, Smith  Smith, John   John Smith   John Smith  TRUE
# 2 Peter, Crouch  Peter, Pan   Crouch Peter  Pan Peter   FALSE

Also you can use the sub function:

"Column 1 | Column 2 
 John, Smith | Smith, John" -> a

df <- read.table(text = a, header = TRUE, sep = '|', strip.white = TRUE)

sub("^(\\w+)(,\\s+)(\\w+)$",  "\\3\\2\\1", df[, 2]) == df[, 1]

[1] TRUE

If your data has not been trimed, then first do.

df[] <- trimws(as.matrix(df))
Related