【问题标题】:I want to join two data frames one with a year range and the other with a year我想加入两个数据框,一个带有年份范围,另一个带有年份
【发布时间】:2021-12-16 14:34:01
【问题描述】:

我有两个看起来像这样的数据框

data1<-data.frame(name=c("Jessica_Smith","John_Smith","John_Smith") ,
max_year=c(2000,1989,2005), 
min_year=c(1990,1989,2001))

data2<-data.frame(name=c("Jessica_Smith","John_Smith","John_Smith") ,
year_of_birth=c(1995,1989,2002),unique_id=c("aby37","nf93","fnd34"))

我想合并数据框,这样对于 data1 中的每个人我都有一个 unique_id。如果可能的话,我还想为那些没有重叠的人获得最接近的整数匹配。为了澄清,我不能只在 name 上 left_join,因为有些条目具有相同的名称但不同的出生日期。

我对 R 比较陌生,所以我什至不知道从哪里开始。

非常感谢!

【问题讨论】:

  • 为什么不只是left_join
  • 当一个df有一个范围而另一个只有一个数字时,你可以使用left_join吗?
  • 如果year_of_birth不在max_year和min_year的范围内怎么办?那么你想删除那一行吗?
  • 如果您需要为那些不适合其中一个区间的人获得最接近的匹配,您确实应该提供实际需要的样本数据。就目前而言,这两种答案都不会产生这种行为。
  • 此外,我怀疑仅一年(而不是姓名)加入会引起很多问题。

标签: r data.table left-join tidyverse fuzzyjoin


【解决方案1】:

使用data.table,您可以进行非等连接:
(添加了一些额外的列和一个与示例不匹配的名称)

library(data.table)
data1<-data.table(name=c("Jessica_Smith","John_Smith","John_Smith", "Jackson_Brown") ,
                  max_year=c(2000,1989,2005,2020), 
                  min_year=c(1990,1989,2001,1990),
                  extra_col1=c('a', 'b', 'c', 'd'))

data2<-data.table(name=c("Jessica_Smith","John_Smith","John_Smith") ,
                  year_of_birth=c(1995,1989,2002),
                  unique_id=c("aby37","nf93","fnd34"),
                  extra_col2=1:3)

data2[data1, .(name, year_of_birth = x.year_of_birth, unique_id,
               extra_col1, extra_col2), 
      on = .(name, year_of_birth >= min_year, year_of_birth <= max_year)]

            name year_of_birth unique_id extra_col1 extra_col2
1: Jessica_Smith          1995     aby37          a          1
2:    John_Smith          1989      nf93          b          2
3:    John_Smith          2002     fnd34          c          3
4: Jackson_Brown            NA      <NA>          d         NA

我认为最好列出要包含在结果中的所有列名。
不等连接的一个困难是“匹配”列的默认重命名。这些列与非相等条件匹配,但它们不相同。这就是我指定 x.year_of_birth 的原因(您可以使用 x. 或 i. 来选择列来自 x[i] 中的哪个 data.table)。

这是未选择列的结果(通常会为您提供连接中的所有列):

data2[data1,
      on = .(name, year_of_birth >= min_year, year_of_birth <= max_year)]

            name year_of_birth unique_id extra_col2 year_of_birth.1 extra_col1
1: Jessica_Smith          1990     aby37          1            2000          a
2:    John_Smith          1989      nf93          2            1989          b
3:    John_Smith          2001     fnd34          3            2005          c
4: Jackson_Brown          1990      <NA>         NA            2020          d

请注意,这里的 year_of_birth 实际上是 min_year,而 year_of_birth.1 实际上是 max_year。所以这很令人困惑,并且 data2$year_of_birth 不包括在内,因为它被认为是不需要保留的“匹配”列。

【讨论】:

  • 很好的答案,只是一个小评论:当您将 data2 加入 data1 时,您的列 year_of_birth 保持正确的值。 data1[data2, .(name, year_of_birth, unique_id), on = .(name, max_year &gt;= year_of_birth, min_year &lt;= year_of_birth)]
  • 我忘记提到的一件事是 data1 和 data2 中的列比列出的要多。我需要列出所有这些还是可以通过一个简单的命令保留所有列?
【解决方案2】:

你可以试试,

data1 %>% 
  left_join(data2, by = "name") %>%
  rowwise %>%
  mutate(year_key = min_year <= year_of_birth && year_of_birth <= max_year) %>%
  filter(year_key == TRUE) %>% 
  select(-year_key)

  name          max_year min_year year_of_birth unique_id
  <chr>            <dbl>    <dbl>         <dbl> <chr>    
1 Jessica_Smith     2000     1990          1995 aby37    
2 John_Smith        1989     1989          1989 nf93     
3 John_Smith        2005     2001          2002 fnd34  

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-05
    • 2019-10-29
    • 2019-09-06
    • 2018-03-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多