Home > OS >  Filtering list column with value in other column
Filtering list column with value in other column

Time:04-14

I am trying to filter a nested dataframe/list column with the value contained in another column of the main (?) dataframe. Unfortunately, my code below doesn't work, and I think the problem is that the way I am referring to search_term inside the map_if is not correct. I suspect that it takes the entire vector/column and not only the single value for each row of search_term. I use map_if to check if the nested nested dataframe, which i want to filter, is not empty (checking is number of rows in nested_data_nrow). Grateful for any hint. Many thanks. Below my reprex.

library(tidyverse)
#> Warning: package 'dplyr' was built under R version 4.1.3
df_nest <- structure(list(nested_data = list(structure(list(places_bank_name = c(
  "ZiraatBank",
  "UniCredit Bank", "Sparkasse Bank", "Intesa Sanpaolo Banka",
  "Raiffeisen BANK", "EKI"
)), row.names = c(NA, -6L), class = c(
  "tbl_df",
  "tbl", "data.frame"
)), structure(list(places_bank_name = c(
  "Raiffeisen BANK (iPoslovnica)",
  "KIB Banka", "Raiffeisen BANK - Agencija Bužim", "BBI Bosna Bank International"
)), row.names = c(NA, -4L), class = c("tbl_df", "tbl", "data.frame")), structure(list(places_bank_name = "Casopis Financing"), row.names = c(
  NA,
  -1L
), class = c("tbl_df", "tbl", "data.frame")), structure(list(
  places_bank_name = "UniCredit Bank"
), row.names = c(NA, -1L), class = c("tbl_df", "tbl", "data.frame"))), nested_data_nrow = c(
  6,
  4, 1, 1
), search_term = c(
  "BBI|Bosna Banka", "Komercijalno-investiciona|KIB",
  "Raiffeisen", "UniCredit"
), bank_name = c(
  "Bosna Banka International",
  "Komercijalno-investiciona banka d.d. V.Kladusa", "Raiffeisen Bank d.d. BiH",
  "UniCredit d.d. Mostar"
)), row.names = c(NA, -4L), class = c(
  "tbl_df",
  "tbl", "data.frame"
))

df_nest
#> # A tibble: 4 x 4
#>   nested_data      nested_data_nrow search_term                   bank_name     
#>   <list>                      <dbl> <chr>                         <chr>         
#> 1 <tibble [6 x 1]>                6 BBI|Bosna Banka               Bosna Banka I~
#> 2 <tibble [4 x 1]>                4 Komercijalno-investiciona|KIB Komercijalno-~
#> 3 <tibble [1 x 1]>                1 Raiffeisen                    Raiffeisen Ba~
#> 4 <tibble [1 x 1]>                1 UniCredit                     UniCredit d.d~

df_nest_filtered <- df_nest %>%
  mutate(nest_data_filtered = map_if(
    nested_data,
    nested_data_nrow > 0,
    ~ .x %>%
      filter(str_detect(
        places_bank_name,
        regex(search_term, ignore_case = T)
      ))
  )) %>%
  mutate(nest_data_filtered_nrow = map_dbl(nest_data_filtered, nrow)) %>%
  select(bank_name, search_term, everything())
#> Warning in stri_detect_regex(string, pattern, negate = negate, opts_regex =
#> opts(pattern)): longer object length is not a multiple of shorter object length
#> Error in `mutate()`:
#> ! Problem while computing `nest_data_filtered = map_if(...)`.
#> Caused by error in `filter()`:
#> ! Problem while computing `..1 = str_detect(places_bank_name,
#>   regex(search_term, ignore_case = T))`.
#> x Input `..1` must be of size 1, not size 4.

Created on 2022-04-13 by the reprex package (v2.0.1)

CodePudding user response:

There are multiple columns going inside map_if and this creates a length issue as each element of nested_data should be matched with the corresponding 'search_term'. Therefore, pmap would be better

library(dplyr)
library(purrr)
library(stringr)
df_nest2 <- df_nest %>%
   mutate(nest_data_filtered = pmap(across(
     c(nested_data, nested_data_nrow, search_term)), 
    ~ if(..2 > 0) ..1 %>%
     filter(str_detect(places_bank_name, 
      regex(..3, ignore_case = TRUE)) ) else ..1))

-output

> df_nest2$search_term
[1] "BBI|Bosna Banka"     
[2] "Komercijalno-investiciona|KIB"
[3] "Raiffeisen"         
[4] "UniCredit"                    
> df_nest2$nest_data_filtered
[[1]]
# A tibble: 0 × 1
# … with 1 variable: places_bank_name <chr>

[[2]]
# A tibble: 1 × 1
  places_bank_name
  <chr>           
1 KIB Banka       

[[3]]
# A tibble: 0 × 1
# … with 1 variable: places_bank_name <chr>

[[4]]
# A tibble: 1 × 1
  places_bank_name
  <chr>           
1 UniCredit Bank  

Or another option is with map2 and case_when

df_nest %>%
   mutate(nest_data_filtered = case_when(nested_data_nrow > 0 
     ~ map2(nested_data, search_term,
    ~ .x %>% filter(str_detect(places_bank_name,
     regex(.y, ignore_case = TRUE)))), TRUE ~ nested_data))
  • Related