基于嵌套成员资格有条件地加入 R 表

Conditionally join R tables based on nested membership

考虑这个示例嵌套数据框,其中包含 3 个县、3 个城镇以及与它们关联的一系列邮政编码。其中两个城镇同名 (B),但位于不同的县:

df <- tibble(
  county = c(1,1,1,2,2,2,2,3),
  town = c("A","A","A","B","B","B","B","B"),
  zip = c(12864,12865,12866,89501,89502,89503,89504,76512)) %>% 
  nest(data=c(zip))

我有另一个包含城镇名称、邮政编码和占位符值的数据框,但缺少县字段:

df2 <- tibble(
  town = c("A", "B", "B"),
  zip = c(12866, 89504, 76512),
  value = c("foo", "bar", "ski"))

我的真实数据有数百个这些重复城镇名称的实例,我需要将这两个表连接在一起,以便每个城镇根据邮政编码获得正确的占位符值(不是城镇名称,它有重复).然而,dplyr似乎只是。因此,我被卡住了 - 我所追求的是 inner_join(df, df2, by = c(df2$zip %in% df$data$zip)) 之类的东西,但这显然行不通。

我也知道 data.table 能够 ,但这似乎总是与比条件句更大的 than/less 相关。在数据帧之间有超过 3 个整齐匹配的行的情况下,我如何才能成功地将这些表连接到 return 以下输出?

  county town  data             value
   <dbl> <chr> <list>           <chr>
1      1 A     <tibble [3 x 1]> foo  
2      2 B     <tibble [4 x 1]> bar  
3      3 B     <tibble [1 x 1]> ski

我认为您必须“自行加入”:

df %>% mutate(value = df2$value[
  sapply(data, function(x) match(unlist(x), df2$zip) %>% .[!is.na(.)])
  ])

这适用于所提供的示例,但我不清楚在一组 df$data$zip 中是否有多个 df2$zip 的匹配项。

我们可以用 map

library(purrr)
library(dplyr)
df %>% 
    mutate(value = map_chr(data, ~ inner_join(.x, df2, by = 'zip') %>% 
          pull(value)))

-输出

# A tibble: 3 × 4
  county town  data             value
   <dbl> <chr> <list>           <chr>
1      1 A     <tibble [3 × 1]> foo  
2      2 B     <tibble [4 × 1]> bar  
3      3 B     <tibble [1 × 1]> ski  

或者另一个选项是 regex_inner_join

library(fuzzyjoin)
library(stringr)
library(dplyr)
library(purrr)
df %>%
    mutate(zip = map_chr(data, ~ str_c(.x$zip, collapse="|"))) %>% 
    regex_inner_join(df2 %>%
          select(-town), by = "zip") %>% 
    select(-starts_with('zip'))

-输出

# A tibble: 3 × 4
  county town  data             value
   <dbl> <chr> <list>           <chr>
1      1 A     <tibble [3 × 1]> foo  
2      2 B     <tibble [4 × 1]> bar  
3      3 B     <tibble [1 × 1]> ski