user25494
user25494

Reputation: 1371

Row-wise comparisons of list columns

Given a dataframe dat with two list columns, composed of character vectors, I would like to use mutate() to create a new column that contains elements of copub that are not present in secondary_report_ids.

I've failed thus far to find a solution using purrr::map() to apply setdiff() in a row-wise fashion.

dat <- structure(list(unique_study_id = c("13", "21", "3", "2", "78"
    ), srdr_id = c("174212", "172787", "174230", "174200", "174408"
    ), secondary_report_ids = list("174299", NA_character_, c("174081", 
    "174817", "174804", "172844", "172845"), c("175114", "174839", 
    "174240"), c("174094", "172575")), copub = list(c("174299", "174202", 
    "174283"), c("172567", "172566", "172621"), c("174817", "174804", 
    "172844", "172845", "174081", "174080", "174079"), c("172501", 
    "172961", "174564", "175114", "172498", "174839", "174240"), 
        c("172575", "174094"))), class = c("spec_tbl_df", "tbl_df", 
    "tbl", "data.frame"), row.names = c(NA, -5L))

Upvotes: 1

Views: 213

Answers (2)

akrun
akrun

Reputation: 887901

Here is an option with pmap

library(tidyverse)
dat %>% 
   mutate(new_col = pmap(list(copub, secondary_report_ids), setdiff))
# A tibble: 5 x 5
#  unique_study_id srdr_id secondary_report_ids copub     new_col  
#  <chr>           <chr>   <list>               <list>    <list>   
#1 13              174212  <chr [1]>            <chr [3]> <chr [2]>
#2 21              172787  <chr [1]>            <chr [3]> <chr [3]>
#3 3               174230  <chr [5]>            <chr [7]> <chr [2]>
#4 2               174200  <chr [3]>            <chr [7]> <chr [4]>
#5 78              174408  <chr [2]>            <chr [2]> <chr [0]>

Upvotes: 1

Ronak Shah
Ronak Shah

Reputation: 389275

We can use map2_chr from purrr

library(dplyr)
library(purrr)

dat %>%
  mutate(new_col = map2_chr(copub, secondary_report_ids, ~toString(setdiff(.x, .y))))

# unique_study_id srdr_id secondary_report_ids copub     new_col                       
#  <chr>           <chr>   <list>           <list>    <chr>                         
#1 13              174212  <chr [1]>        <chr [3]> 174202, 174283                
#2 21              172787  <chr [1]>        <chr [3]> 172567, 172566, 172621        
#3 3               174230  <chr [5]>        <chr [7]> 174080, 174079                
#4 2               174200  <chr [3]>        <chr [7]> 172501, 172961, 174564, 172498
#5 78              174408  <chr [2]>        <chr [2]> ""                     

The above gives a single comma-separated string for every row.

If you want the final output to be another list, we can just use map2

dat %>%
  mutate(new_col = map2(copub, secondary_report_ids, setdiff))

# unique_study_id srdr_id secondary_report_ids copub     new_col  
# <chr>           <chr>   <list>               <list>    <list>   
#1 13              174212  <chr [1]>            <chr [3]> <chr [2]>
#2 21              172787  <chr [1]>            <chr [3]> <chr [3]>
#3 3               174230  <chr [5]>            <chr [7]> <chr [2]>
#4 2               174200  <chr [3]>            <chr [7]> <chr [4]>
#5 78              174408  <chr [2]>            <chr [2]> <chr [0]>

In base R we can use mapply

mapply(function(x, y) toString(setdiff(x, y)), dat$copub, dat$secondary_report_ids)

and

mapply(setdiff, dat$copub, dat$secondary_report_ids)

Upvotes: 2

Related Questions