范围 overlap/intersect 按组别和年份

Range overlap/intersect by group and between years

我有一个标记个体列表(Mark 列),这些个体在河流范围(LocStart 和 LocEnd)内的不同年份(Year 列)被捕获。在河上的位置以米为单位。

我想知道一个被标记的个体是否在不同年份之间使用过重叠范围,即该个体是否每年都去过河流的同一段。

这里是原始数据集的例子:

IDMark YearLocStartLocEnd
11081199221,72922,229
21081199221,20321,703
31081200521,50822,008
41126199419,22219,522
51126199418,81119,311
61283200521,75422,254
71283200722,02522,525

我希望最终答案如下所示:

MarkYear1Year2IDs
1081199220051, 3
1081199220052, 3
1283200520076, 7

在这种情况下,个人 1126 不会出现在最终输出中,因为仅有的两个可用范围是同一年。我意识到删除 Year1 = Year2 的所有记录很容易。

我想在 R 中执行此操作并查看了 >IRanges 包,但无法考虑组 = 标记并能够提取 Year1 和 Year2 信息。

使用 data.table 包中的 foverlaps() 函数:

require(data.table)
setkey(setDT(dt), Mark, LocStart, LocEnd)               ## (1)
olaps = foverlaps(dt, dt, type="any", which=TRUE)       ## (2)
olaps = olaps[dt$Year[xid] != dt$Year[yid]]             ## (3)
olaps[, `:=`(Mark  = dt$Mark[xid], 
             Year1 = dt$Year[xid],
             Year2 = dt$Year[yid],
             xid   = dt$ID[xid], 
             yid   = dt$ID[yid])]                       ## (4)
olaps = olaps[xid < yid]                                ## (5)
#    xid yid Mark Year1 Year2
# 1:   2   3 1081  1992  2005
# 2:   1   3 1081  1992  2005
# 3:   6   7 1283  2005  2007
  1. 我们首先通过引用将data.frame转换为data.tablesetDT。然后,我们在 MarkLocStartLocEnd 列上 key data.table,这将允许我们执行重叠范围连接。

  2. 我们计算自我重叠dt与自身)与任何类型的重叠。但是我们 return 在这里使用 which = TRUE.

  3. 匹配索引
  4. 删除所有 Year 对应 xidyid 相同的索引。

  5. 添加所有其他列并将 xidyid 替换为相应的 ID 值,以供参考。

  6. 删除所有 xid >= yid 的索引。如果第 1 行与第 3 行重叠,则第 3 行也与第 1 行重叠。我们不需要两者。 foverlaps() 默认情况下还没有办法删除它。