在数据框中查找重叠范围并为其分配值
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
。
这是input
和output
的输入:
> 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
应该相同,在这种情况下为 chr1
。 input[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
,它与CT1
的chr2: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"
)。你能指导我这里出了什么问题吗?谢谢。以上是关于在数据框中查找重叠范围并为其分配值的主要内容,如果未能解决你的问题,请参考以下文章