在数据框中查找重叠范围并为其分配值

Posted

技术标签:

【中文标题】在数据框中查找重叠范围并为其分配值【英文标题】:Find overlapping ranges in a dataframe and assign them values 【发布时间】:2018-01-11 12:30:22 【问题描述】:

原始question 的一个更简单的版本,我问过,但还没有人回答。

我有一个巨大的输入文件(其代表性示例如下所示为input):

> input
           CT1           CT2           CT3
1 chr1:200-400  chr1:250-450  chr1:400-800
2 chr1:800-970  chr2:200-500  chr1:700-870
3 chr2:300-700 chr2:600-1000 chr2:700-1400

我想按照规则(如下所述)处理它,以便我得到 output 之类的:

 > output
              CT1 CT2 CT3
chr1:200-400    1   1   0
chr1:800-970    1   0   1
chr2:300-700    1   1   0
chr1:250-450    1   1   1
chr2:200-500    1   1   0
chr2:600-1000   1   1   1
chr1:400-800    0   1   1
chr1:700-870    1   0   1
chr2:700-1400   0   1   1

规则: 获取数据帧的每个索引(在这种情况下第一个是chr1:200-400),看看它是否与数据帧中的任何其他值重叠。如果是,在它所在的那一列下面写1,如果不是,写0

例如,如果我们采用输入input[1,1] 的第一个索引,即chr1:200-400。由于它存在于第 1 列中,我们将在其下方写 1。现在我们将检查此范围是否与input 中任何其他列中存在的任何其他范围重叠。该值仅与第二列 (CT2) 的第一个值 (chr1:250-450) 重叠,因此,我们也在其下方写入 1。由于与CT3 中的任何值都没有重叠,我们在输出数据帧中的CT3 下方写入0

这是inputoutput的输入:

> dput(input)
structure(list(CT1 = structure(1:3, .Label = c("chr1:200-400", 
"chr1:800-970", "chr2:300-700"), class = "factor"), CT2 = structure(1:3, .Label = c("chr1:250-450", 
"chr2:200-500", "chr2:600-1000"), class = "factor"), CT3 = structure(1:3, .Label = c("chr1:400-800", 
"chr1:700-870", "chr2:700-1400"), class = "factor")), .Names = c("CT1", 
"CT2", "CT3"), class = "data.frame", row.names = c(NA, -3L))
> dput(output)
structure(list(CT1 = c(1L, 1L, 1L, 1L, 1L, 0L, 0L, 0L, 0L), CT2 = c(1L, 
0L, 1L, 1L, 1L, 1L, 0L, 1L, 1L), CT3 = c(0L, 0L, 0L, 0L, 0L, 
1L, 1L, 1L, 1L)), .Names = c("CT1", "CT2", "CT3"), class = "data.frame", row.names = c("chr1:200-400", 
"chr1:800-970", "chr2:300-700", "chr1:250-450", "chr2:200-500", 
"chr2:600-1000", "chr1:400-800", "chr1:700-870", "chr2:700-1400"
))

【问题讨论】:

所以这是您其他问题的准确副本? 不是确切的副本,规则有点复杂,我想要1 仅用于那些超过总范围 50% 的重叠。在这里,我只要求重叠。如果有任何重叠,分配 1。 1.将宽转换为长, 2. 将字符串解析为 3 列“chr、start、end”。 3. 在 CT 上拆分,4. 在重叠上合并,example1,example2 等 您需要定义“重叠”,因为我无法理解您的输出中零和一的分配 - 我会期待其他的东西 @RolandASc input[1,1] (200-400) 和 input[1,2] (250-400) 之间的重叠为 150。此外,chr 应该相同,在这种情况下为 chr1input[1,1] 区域与 input[,3] 区域中的任何一个都没有重叠,因为 chr1 从 400 开始。现在有意义吗? 【参考方案1】:

使用data.table-package 的可能解决方案:

# load the 'data.table'-package and convert 'input' to a data.table with 'setDT'
library(data.table)
setDT(input)

# reshape 'input' to long format and split the strings in 3 columns
DT <- melt(input, measure.vars = 1:3)[, c('chr','low','high') := tstrsplit(value, split = ':|-', type.convert = TRUE)
                                      , by = variable][]

# create aggregation function; needed in the ast reshape step
f <- function(x) as.integer(length(x) > 0)

# cartesian self join & reshape result back to wide format with aggregation function
DT[DT, on = .(chr, low < high, high > low), allow.cartesian = TRUE
   ][, dcast(.SD, value ~ i.variable, fun = f)]

给出:

           value CT1 CT2 CT3
1:  chr1:200-400   1   1   0
2:  chr1:250-450   1   1   1
3:  chr1:400-800   0   1   1
4:  chr1:700-870   1   0   1
5:  chr1:800-970   1   0   1
6:  chr2:200-500   1   1   0
7:  chr2:300-700   1   1   0
8: chr2:600-1000   1   1   1
9: chr2:700-1400   0   1   1

【讨论】:

非常感谢您提出详细的解决方案。我认为这里有一个问题,对于区域chr2:200-500,它与CT1chr2:300-700 重叠,但输出中的值为0。 @Newbie 我认为应该在行中检查重叠。如果我理解正确,那是没有必要的。查看更新。 HTH 现在一切正常。我认为您在更新中删除了rn 部分。您能否建议我如何再设置一个条件来选择重叠。即仅当被比较的两个范围中的任何一个与其整个范围的 50% 以上重叠时才分配 1。例如,200-400 和 300-450 之间的重叠将被视为 1(实际重叠为 100,超过整个第二范围 150 的 50%),但 200-400 和 350-550 之间的重叠将被视为 0。 @Newbie 今晚会尝试看看它 当我将这段代码应用于也包含 NA 的维度 (66186*23) 的实际数据时,该代码存在问题。我只得到前三列的结果。我检查了我的实际输入数据的类别,它与此处提供的输入样本相同 ("data.table" "data.frame")。你能指导我这里出了什么问题吗?谢谢。

以上是关于在数据框中查找重叠范围并为其分配值的主要内容,如果未能解决你的问题,请参考以下文章

在R中的数据帧范围中发现重叠

核心数据 - 查找具有重叠日期范围的记录

查找与给定范围重叠的所有范围

PL/SQL:在由开始和结束定义的重叠日期范围内查找孤岛

查找两个整数范围之间的重叠区域

特定时间范围内的重叠计数