【问题标题】:Join datasets with dates ranges加入具有日期范围的数据集
【发布时间】:2022-01-14 16:51:46
【问题描述】:

我有两个数据集,我想在 R 中使用 inner_join 进行合并。问题是第二个数据集包含日期范围,我想保留这些信息。如何将第一个数据集的日期与第二个数据集的日期范围相匹配?下面是一个工作示例。

非常感谢。

library(data.table)
library(dplyr)

# First Dataset
dt_1 <- data.table()
dt_1$city <- c("madrid","milan","milan","paris", "Rome")
dt_1$address <- c("a","a","b","c","d")
dt_1$date_1 <- c( "2017", "2013", "2008", "1901","2009")
dt_1


# Second dataset
dt_2 <- data.table()
dt_2$city <- c("milan","madrid","Porto","Barcelona", "Rome")
dt_2$address <- c("a","a","b","c","d")
dt_2$date_1 <- c( "2012", "2016", "2006", "1900","2009")
dt_2$date_2 <- c( "2015", "NA", "2022", "1930","NA")
dt_2


## How to match the corresponding exact dates of the two datasets BUT ALSO the dates falling -
## in the ranges

# This keeps only if the first date is the same
dt_match <- inner_join(dt_1, dt_2, by = c("city","address","date_1"), keep = TRUE)


# How to achieve this ? 
dt_match <- data.table()
dt_match$city <- c("milan","Rome")
dt_match$address <- c("a","c")
dt_match$date <- c( "2013","2009")
dt_match

【问题讨论】:

  • (1) 您的值需要使用数字,而不是字符串。为什么? "222" &gt;= "2017" 是真的,因为它的字典排序。使用as.integer(或as.numeric)修复。 (2) 这不是一个连接:如果是,那么dt_1[2,] 将在dt_2[3,] 中找到匹配项。看来 Waldi 是正确的,这只是逐行比较。 (3) 如果它一个连接,但是,在固定数字之后,开始可能是dt_1[dt_2, date_2 := i.date_2, on = .(date_1 &gt;= date_1, date_1 &lt;= date_2)]

标签: r data.table


【解决方案1】:

根据预期的结果,看起来像是逐行比较:

setDT(dt_1)
setDT(dt_2)
dt <- cbind(dt_1,dt_2)
setnames(dt,c("date_1","start","end"))
dt[,end:= fifelse(end=="NA",start,end)]
dt[,.(date_1=fifelse(date_1 %between% .(start,end),date_1,NA))]

   date_1
   <char>
1:   2013
2:   <NA>
3:   2008
4:   1901
5:   2009

如果这不是逐行比较,则 2017 应该属于结果,因为它属于范围 2006-2022 (dt_2[3])

【讨论】:

  • 非常感谢您的回答,我编辑了这个问题,因为这似乎是一个行比较,但实际上我想实现基于另外两列的匹配。
  • 那么@r2evans 在 cmets 中的回答是正确的 ;-)
【解决方案2】:

感谢您的建议,我根据您的代码进行了调整,我使用的解决方案一点也不优雅,但应该可以:

dt_3 <- inner_join(dt_1, dt_2, by = c("city","address"), keep = TRUE)

dt_3$found_range <- ifelse(sapply(seq_along(dt_3$date_1), function(i) {
  inds <- dt_3$date_2 <= dt_3$date_1[i] & dt_3$date_3 >= dt_3$date_1[i]
  any(inds) & (dt_3$city[i] == dt_3$city[which.max(inds)])
}), 1, NA)
dt_3

dt_3$found_date <- ifelse(sapply(seq_along(dt_3$date_1), function(i) {
  inds <- dt_3$date_2 == dt_3$date_1[i]
  any(inds) & (dt_3$city[i] == dt_3$city[which.max(inds)])
}), 1, NA)

dt_3

dt_3$found_comb <- rowSums(dt_3[,c("found_range", "found_date")], na.rm=TRUE)
dt_3
dt_3[!dt_3$found_comb == 0]

【讨论】:

  • 不幸的是,对于大型数据集,此代码太慢(> 2 小时才能运行)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-30
  • 2017-04-27
  • 2011-01-19
相关资源
最近更新 更多