我想推断不同样本之间的共享基因组间隔。
我的意见:
sample chr start end
NE001 1 100 200
NE001 2 100 200
NE002 1 50 150
NE002 2 50 150
NE003 2 250 300
我的预期输出:
chr start end freq
1 100 150 2
2 100 150 2
" freq"是有多少样本有助于推断共享区域。在上面的示例中,freq = 2(NE001和NE002)。
干杯!
答案 0 :(得分:6)
如果您的数据位于data.frame中(请参见下文),请使用Bioconductor GenomicRanges包创建一个GRanges实例,同时保留非范围列
library(GenomicRanges)
gr <- makeGRangesFromDataFrame(df, TRUE)
由数据表示的离散范围由disjoin
函数给出,并且不相交的范围(&#39;查询&#39;)与您的原始(&#39;主题&#39;是
d <- disjoin(gr)
olaps <- findOverlaps(d, gr)
使用相应的查询拆分与每个重叠主题相关联的样本信息,并将其与不相交的GRanges关联为
mcols(d) <- splitAsList(gr$sample[subjectHits(olaps)], queryHits(olaps))
导致例如
> d[elementLengths(d$value) > 1]
GRanges with 2 ranges and 1 metadata column:
seqnames ranges strand | value
<Rle> <IRanges> <Rle> | <CharacterList>
[1] 1 [100, 150] * | NE001,NE002
[2] 2 [100, 150] * | NE001,NE002
---
seqlengths:
1 2
NA NA
以下是我输入数据的方式:
txt <- "sample chr start end
NE001 1 100 200
NE001 2 100 200
NE002 1 50 150
NE002 2 50 150
NE003 2 250 300"
df <- read.table(textConnection(txt), header=TRUE, stringsAsFactors=FALSE)
答案 1 :(得分:3)
鉴于这个问题背后的背景,我怀疑你是否值得学习Bioconductor的GenomicRanges
包。
library(GenomicRanges)
gr <- GRanges(seqnames=df$chr, ranges=IRanges(start=df$start, end=df$end))
ov <- findOverlaps(gr,gr, type="any")
ov <- ov[queryHits(ov) != subjectHits(ov)]
between <- pintersect(gr[subjectHits(ov)], gr[queryHits(ov)])
方法是:找到所有自我重叠,删除与自身比较间隔的平凡值(第4行),然后找到每对剩余间隔之间的交集。然后,您可以根据需要将结果制成表格。
答案 2 :(得分:1)
这肯定很长(并且在给定expand.grid.df的情况下对大型数据框架效率可能很低,但是,我希望它给你一个起点。作为一个警告,我没有基因组学背景(我是“肯定会来的。所以不知道这方面的常见方法。当然这是最好的方法。我只是觉得尝试解决方案会很有趣。
s<-"sample chr start end
NE001 1 100 200
NE001 2 100 200
NE002 1 50 150
NE002 2 50 150
NE003 2 250 300"
dat<-read.table(text=s, header=T)
library(plyr)
between<-function(x,y,z) x<=y & y<=z
dat$id<-seq_along(dat[,1])
expand.grid.df <- function(...) Reduce(function(...) merge(..., by=NULL), list(...))
expdat<-ddply(dat, .(chr), function(x) expand.grid.df(x,x))
expdat<-subset(expdat, id.x!=id.y)
expdat$betweenL<-with(expdat, between(start.y, start.x, end.y))
expdat$betweenR<-with(expdat, between(start.x, start.y, end.x))
expdat<-subset(expdat, betweenL | betweenR)
expdat$commonstart<-with(expdat,ifelse(betweenL,start.x,start.y))
expdat$commonend<-with(expdat, ifelse(betweenL, end.y, end.x))
res<-ddply(expdat, .(chr, commonstart, commonend),summarize, freq=length(sample.x))
> res
chr commonstart commonend freq
1 1 100 150 2
2 2 100 150 2