【问题标题】:merge by nearest neighbour in group - R按组中最近的邻居合并 - R
【发布时间】:2021-10-04 09:37:57
【问题描述】:

我有两个覆盖相同国家但不同年份的国家*年份级别的数据集。我想以某种方式合并两者,使年份与其最近的邻居匹配,始终在国家/地区内(iso2code)。

第一个 (dat1) 看起来像这样(这里只显示 AT 的头部,但 iso2code 有多个不同的值):

  iso2code  year elect_polar_lrecon
  <chr>    <dbl>              <dbl>
1 AT        1999               2.48
2 AT        2002               4.18
3 AT        2006               3.66
4 AT        2010               3.91
5 AT        2014               4.01
6 AT        2019               3.55

第二个(dat2)看起来像这样:

  iso2code  year affpol
  <chr>    <dbl>  <dbl>
1 AT        2008   2.47
2 AT        2013   2.49
3 DE        1998   2.63
4 DE        2002   2.83
5 DE        2005   2.89
6 DE        2009   2.09

最后我想要类似的东西(请注意,2008 年的 affpol 值可以与 2010 年和 2006 年匹配,因为它与两者的距离相等。如果可能,我会选择最近的日期,如下所示):

  iso2code  year.1 elect_polar_lrecon year.2 affpol
  <chr>    <dbl>                <dbl>  <dbl>  <dbl>
1 AT        1999                 2.48  
2 AT        2002                 4.18  
3 AT        2006                 3.66  
4 AT        2010                 3.91  2008    2.47
5 AT        2014                 4.01  2013    2.49
6 AT        2019                 3.55  

不确定如何执行此操作...我很高兴有一个 tidyverse 解决方案,但真的,非常感谢所有帮助!

【问题讨论】:

标签: r tidyverse


【解决方案1】:

正如Henrik 所提到的,这可以通过在滚动连接中更新到最近来解决,这在 包中提供。此外,如果匹配距离相同,OP 已要求选择最近的日期

library(data.table)
setDT(dat1)[setDT(dat2), roll = "nearest", on = c("iso2code", "year"), 
     `:=`(year.2 = i.year, affpol = i.affpol)]

dat1
   iso2code year elect_polar_lrecon year.2 affpol
1:       AT 1999               2.48     NA     NA
2:       AT 2002               4.18     NA     NA
3:       AT 2006               3.66   2008   2.47
4:       AT 2010               3.91     NA     NA
5:       AT 2014               4.01   2013   2.49
6:       AT 2019               3.55     NA     NA

此操作已通过引用更新dat1,即,无需通过添加两个附加列来复制整个数据对象。

现在,如果匹配距离相同但加入选择了较旧的日期,则 OP 已请求选择最近的日期。显然,在滚动连接到最近中没有参数可以控制这一点。

解决方法是创建一个辅助变量nyear 来保存负年份,然后加入:

setDT(dat1)[, nyear := -year][setDT(dat2)[, nyear := -year], 
                              roll = "nearest", on = c("iso2code", "nyear"), 
                             `:=`(year.2 = i.year, affpol = i.affpol)][
                               , nyear := NULL]
dat1
   iso2code year elect_polar_lrecon year.2 affpol
1:       AT 1999               2.48     NA     NA
2:       AT 2002               4.18     NA     NA
3:       AT 2006               3.66     NA     NA
4:       AT 2010               3.91   2008   2.47
5:       AT 2014               4.01   2013   2.49
6:       AT 2019               3.55     NA     NA

【讨论】:

    【解决方案2】:

    我在朋友的帮助下弄明白了。我把它留在这里,以防其他人正在寻找解决方案。假设第一个数据集是to_plot,第二个数据集称为to_plot2。那么:

    find_nearest_year <- function(p_year, p_code){
    
    years <- to_plot$year[to_plot$iso2code==p_code] 
    
    nearest_year <- years[1]
    
    for (i in sort(years, decreasing = TRUE)) {
      if (abs(i - p_year) < abs(nearest_year-p_year)) {
        nearest_year <- i
      }
    }
    
    return(nearest_year)
      
    }
    
    to_plot2 <- to_plot2 %>%
      group_by(iso2code, year) %>%
      mutate(matching_year=find_nearest_year(year, iso2code))
    
    merged <- left_join(to_plot, to_plot2, by=c("iso2code", "year"="matching_year"))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-19
      • 2018-09-06
      • 2020-11-05
      • 1970-01-01
      相关资源
      最近更新 更多