Usman Khaliq
Usman Khaliq

Reputation: 363

Determine whether any value from vector in R is found in another vector

I have a data frame that has two columns, a and b. Both a and b have vectors of different lengths, and I want to create another column, called boolean, which should be true when at least one value from the vector in b is present in the vector in column a. However, I used the following logic and I'm getting a false for all rows, even though I should be getting true for rows 1, 3 and 4. A reproducible example of my attempt is as follows:

library(tidyverse)
library(tibble)
data_frame <-
  tribble(
    ~a,                                    ~b,
    c("50", "50", "50", "3"),              c("1", "2", "3"),
    c("17", "50", "50", "50"),             "19",
    c("50", "28", "50", "3"),              c("30", "28", "29"),
    c("21", "19", "50", "50", "50"),       c("19", "20", "18")
  )

data_frame %>% 
  mutate(
    boolean = if_else(
      any(b %in% a),
      "yes",
      "no"
    )
  )
#> # A tibble: 4 x 3
#>   a         b         boolean
#>   <list>    <list>    <chr>  
#> 1 <chr [4]> <chr [3]> no     
#> 2 <chr [4]> <chr [1]> no     
#> 3 <chr [4]> <chr [3]> no     
#> 4 <chr [5]> <chr [3]> no

Is there something wrong with how I am using the any command? Thanks.

Upvotes: 1

Views: 113

Answers (5)

akrun
akrun

Reputation: 886938

We can use pmap

library(dplyr)
library(purrr)
data_frame %>% 
   mutate(boolean = pmap_chr(., ~  c("no", "yes")[1+any(..2 %in% ..1)]))
# A tibble: 4 x 3
#  a         b         boolean
#  <list>    <list>    <chr>  
#1 <chr [4]> <chr [3]> yes    
#2 <chr [4]> <chr [1]> no     
#3 <chr [4]> <chr [3]> yes    
#4 <chr [5]> <chr [3]> yes    

Upvotes: 0

ThomasIsCoding
ThomasIsCoding

Reputation: 101064

A base R option using Vectorize + intersect

within(data_frame,  boolean <- ifelse(lengths(Vectorize(intersect)(a,b)),"yes","no"))

or Map + intersect

within(data_frame,  boolean <- ifelse(lengths(Map(intersect,a,b)),"yes","no"))

which gives

# A tibble: 4 x 3
  a         b         boolean
  <list>    <list>    <chr>
1 <chr [4]> <chr [3]> yes
2 <chr [4]> <chr [1]> no
3 <chr [4]> <chr [3]> yes
4 <chr [5]> <chr [3]> yes

Upvotes: 3

Darren Tsai
Darren Tsai

Reputation: 35554

A purrr solution with map2():

library(dplyr)
library(purrr)

data_frame %>%
  mutate(boolean = map2_chr(a, b, ~ if_else(any(.y %in% .x), "yes", "no")))

# # A tibble: 4 x 3
#   a         b         boolean
#   <list>    <list>    <chr>  
# 1 <chr [4]> <chr [3]> yes    
# 2 <chr [4]> <chr [1]> no     
# 3 <chr [4]> <chr [3]> yes    
# 4 <chr [5]> <chr [3]> yes    

or with pmap():

data_frame %>%
  mutate(boolean = pmap_chr(select(., a, b),
                            ~ if_else(any(.y %in% .x), "yes", "no")))

Upvotes: 2

Paul van Oppen
Paul van Oppen

Reputation: 1495

Are you after this?

data_frame %>%
  rowwise() %>%
  mutate(boolean = if_else(any(b %in% a), "yes", "no"))

# A tibble: 4 x 3
# Rowwise: 
  a         b         boolean
  <list>    <list>    <chr>  
1 <chr [4]> <chr [3]> yes    
2 <chr [4]> <chr [1]> no     
3 <chr [4]> <chr [3]> yes    
4 <chr [5]> <chr [3]> yes 

Upvotes: 0

Ronak Shah
Ronak Shah

Reputation: 388817

Add rowwise to perform this operation on each row :

library(dplyr)

data_frame %>% 
   rowwise() %>%
   mutate(boolean = if_else(any(b %in% a),"yes","no"))

#   a         b       boolean
#  <list>    <list>    <chr>  
#1 <chr [4]> <chr [3]> yes    
#2 <chr [4]> <chr [1]> no     
#3 <chr [4]> <chr [3]> yes    
#4 <chr [5]> <chr [3]> yes    

Similar variations :

Without ifelse :

library(dplyr)
library(purrr)

data_frame %>% 
  rowwise() %>%
  mutate(boolean = c('no', 'yes')[any(b %in% a) + 1])

Or with map2_lgl :

data_frame %>% 
     mutate(boolean = c('no', 'yes')[map2_lgl(b, a, ~any(.x %in% .y)) + 1])

Upvotes: 2

Related Questions