【问题标题】:Overlap ranges in single dataframe单个数据框中的重叠范围
【发布时间】:2016-10-19 10:58:06
【问题描述】:

我希望在我的 df 中标记具有重叠范围的行(希望创建重叠列)基于一系列数字变量(Min,Max),如果需要,我可以将其转换为整数:

Class    Min  Max
    A    100  200
    A    120  205
    A    210  310
    A    500  630
    A    510  530
    A    705  800

转化为:

Class    Min  Max  Overlap
    A    100  200        1
    A    120  205        1
    A    210  310        0
    A    500  630        1
    A    510  530        1
    A    705  800        0

我尝试过 IRange,但没有取得多大成功 - 有什么想法吗?

【问题讨论】:

  • 您想成对测试所有区间的重叠吗?你确定你需要这个吗?
  • 我认为逻辑可以这样工作:overlap = [ (minVal > any other min) AND ( minVal < maxVal ) ] OR [ (maxVal < any other max) AND ( maxVal > minVal ) ] 对吗?
  • 有了IRanges,看来你只需要countOverlaps(IRanges(dat$Min, dat$Max)) - 1

标签: r


【解决方案1】:

我发现 data.table 对做重叠非常有效,使用 foverlaps

 library(data.table)

重新创建数据:

dt <- data.table(Class = c("A", "A", "A", "A", "A", "A"),
           Min = c(100, 120, 210, 500, 510, 705),
           Max = c(200, 205, 310, 630, 530, 800))

键入 data.table,这是函数所必需的:

setkey(dt, Min, Max)

在这里,我们对自身执行foverlaps,然后过滤,删除那些与自身重叠的行。然后按MinMax 分组计算行数。

dt_overlaps <- foverlaps(dt, dt, type = "any")[Min != i.Min & Max != i.Max, .(Class, Overlap = .N), by = c("Min", "Max")]

感谢大卫阿伦伯格

dt[dt_overlaps, Overlap := 1]

结果:

> dt
  Class Min Max Overlap
1     A 100 200       1
2     A 120 205       1
3     A 210 310      NA
4     A 500 630       1
5     A 510 530       1
6     A 705 800      NA

可能有更简洁的 data.table 代码,但我也在学习。

【讨论】:

  • 如果你想使用data.table 进行连接,你可以使用dt[dt_overlaps, Overlap := 1] ; dt 来修改dt。但是这个解决方案的问题是,对于足够大的数据,OP 可能会很快耗尽内存
【解决方案2】:

outer 是我快速进行成对比较的首选函数。您可以使用outer 创建区间端点的成对比较,然后以您想要的任何方式组合比较。在这种情况下,我检查重叠所需的两条规则是否同时成立。

library(dplyr)

df_foo = read.table(
textConnection("Class    Min  Max
A    100  200
A    120  205
A    210  310
A    500  630
A    510  530
A    705  800"), header = TRUE
)

c = outer(df_foo$Max, df_foo$Min, ">")
d = outer(df_foo$Min, df_foo$Max, "<")

df_foo %>% 
  mutate(Overlap = apply(c & d, 1, sum) > 1 
)

【讨论】:

  • 这可能会很快耗尽内存,dplyrapply 的边距为 1 是为了什么? df_foo$Overlap &lt;- rowSums(c &amp; d) &gt; 1 有什么问题?
  • @DavidArenburg 就内存使用而言,我认为您不能做的比这更少,但这是有待探索的其他答案。
  • @DavidArenburg 至于您的其他问题,这些只是语义。两者都没有真正的意义。
  • 这些不仅仅是语义。边距为1apply 的效率远低于rowSums。并且加载不必要的依赖项似乎完全没有必要
  • @DavidArenburg 在您即将贡献的代码中不需要,而不是在我的代码中。 :-)
【解决方案3】:
library(dplyr)
df_foo%>%mutate(flag=coalesce(ifelse(Max>lead(Min),1,NA),ifelse(lag(Max)>Min,1,NA)))
  Class Min Max flag
1     A 100 200    1
2     A 120 205    1
3     A 210 310   NA
4     A 500 630    1
5     A 510 530    1
6     A 705 800   NA

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-22
    • 2020-08-26
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-19
    相关资源
    最近更新 更多