Reputation: 363
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
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
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
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
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
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