生成属于大范围范围内的值的数据框

时间:2016-03-01 03:11:32

标签: r bioinformatics

我正在接受一系列中位数并检查它们是否介于多个范围之间,然后存储匹配的中位数以及与之相关的标签。此代码有效,但文件对于此迭代方法来说太大了。有没有更快的方法进行这些比较并在数据框中记录匹配?

tfFile的结构是:

    V1        V2        V3   V4    Center_Point
1  chr3 158289024 158289224 CMYC    158289124
2  chr1 242601432 242601632 KLF4    242601532
3 chr11  85912879  85913079 CMYC     85912979
4 chr14  86369800  86370000 SOX2     86369900
5  chr6   8397251   8397451 SOX2      8397351
6  chr3 123709437 123709637 SOX2    123709537

范围的结构是:

   V1       V2       V3        
1 chr1 11323785 11617177 
2 chr1 12645605 13926923 
3 chr1 14750216 15119039
4 chr1 18102157 19080189 
5 chr1 29491029 30934636 
6 chr1 33716472 35395979 

在这里查看代码:

tfFile = read.table("medianfile.txt", sep= "", stringsAsFactors=FALSE)
ranges = read.table("ranges.txt", sep= "", stringsAsFactors=FALSE)
centerdf <- data.frame('Center_Point' = numeric(0))
Center_Point<-apply(tfFile[c('V2', 'V3')], 1, median, na.rm=TRUE)
data<-cbind(tfFile,Center_Point)
tempdf = data.frame( 'Center_Point' = numeric(0), "TF" = character(0),stringsAsFactors = FALSE)
generatedata<-function(data, lamina){
matchesdf <- data.frame( 'Center_Point' = numeric(0), "TF" = character(0),    stringsAsFactors = FALSE)

#Making the comparisons
for(j in 1:nrow(data)){
  for(k in 1:nrow(ranges)){
  #if the value falls within the LADs
    if(data$Center_Point[j]< ranges$V3[k] && data$Center_Point[j]>ranges$V2[k]){
      tempdf<-data.frame(Center_Point = data$Center_Point[j], TF = data$V4[j])
      matchesdf <- rbind(matchesdf, tempdf)
   } 
 }
}
return(matchesdf)
}
a<-generatedata(data, ranges)

2 个答案:

答案 0 :(得分:2)

请参阅我的评论 - 我不确定您正在尝试做什么,但似乎有data.table加入的风格。我已将您的表格复制为data.table,以便:

> d1
     chr       low      high sthg       mid
1:  chr1 242601432 242601632 KLF4 242601532
2: chr11  85912879  85913079 CMYC  85912979
3: chr14  86369800  86370000 SOX2  86369900
4:  chr3 158289024 158289224 CMYC 158289124
5:  chr3 123709437 123709637 SOX2 123709537
6:  chr6   8397251   8397451 SOX2   8397351
> d2
    chr range.low range.high
1: chr1  11323785   11617177
2: chr1  12645605   13926923
3: chr1  14750216   15119039
4: chr1  18102157   19080189
5: chr1  29491029   30934636
6: chr1  33716472   35395979

我也做过

setkey(d1,chr)
setkey(d2,chr)

现在,我可以在chr列中加入这些内容,因此当chr匹配时,您会看到每个范围:

> d2[d1]
      chr range.low range.high       low      high sthg       mid
 1:  chr1  11323785   11617177 242601432 242601632 KLF4 242601532
 2:  chr1  12645605   13926923 242601432 242601632 KLF4 242601532
 3:  chr1  14750216   15119039 242601432 242601632 KLF4 242601532
 4:  chr1  18102157   19080189 242601432 242601632 KLF4 242601532
 5:  chr1  29491029   30934636 242601432 242601632 KLF4 242601532
 6:  chr1  33716472   35395979 242601432 242601632 KLF4 242601532
 7: chr11        NA         NA  85912879  85913079 CMYC  85912979
 8: chr14        NA         NA  86369800  86370000 SOX2  86369900
 9:  chr3        NA         NA 158289024 158289224 CMYC 158289124
10:  chr3        NA         NA 123709437 123709637 SOX2 123709537
11:  chr6        NA         NA   8397251   8397451 SOX2   8397351

现在,您可以使用简单的data.table操作进行单次传递,并确定中间点落在范围内的位置:

d <- d2[d1]
d[!is.na(range.low+range.high),
  falls.in.range:=(range.low <= mid & mid <= range.high)]
d

     chr range.low range.high       low      high sthg       mid falls.in.range
 1:  chr1  11323785   11617177 242601432 242601632 KLF4 242601532          FALSE
 2:  chr1  12645605   13926923 242601432 242601632 KLF4 242601532          FALSE
 3:  chr1  14750216   15119039 242601432 242601632 KLF4 242601532          FALSE
 4:  chr1  18102157   19080189 242601432 242601632 KLF4 242601532          FALSE
 5:  chr1  29491029   30934636 242601432 242601632 KLF4 242601532          FALSE
 6:  chr1  33716472   35395979 242601432 242601632 KLF4 242601532          FALSE
 7: chr11        NA         NA  85912879  85913079 CMYC  85912979             NA
 8: chr14        NA         NA  86369800  86370000 SOX2  86369900             NA
 9:  chr3        NA         NA 158289024 158289224 CMYC 158289124             NA
10:  chr3        NA         NA 123709437 123709637 SOX2 123709537             NA
11:  chr6        NA         NA   8397251   8397451 SOX2   8397351             NA

不是一个很好的例子,因为chr1个案件似乎都没有达到这个条件,但希望这可以解决问题。

需要注意的关键是data.table联接的速度非常快,因此如果正确选择连接列,即使在大型表上也应该能够利用快速连接,然后再进行一次传递通过这张大桌子。您可能需要根据特定问题考虑交叉连接。 (另请参阅:?CJ中的allow.cartesian和可能?data.table。)

编辑,如果确实意味着您想知道每个范围是否每个中点落在该范围内,那么是,您处于交叉连接区域。请注意,这意味着您基本上认为&#34; chr1&#34; -style和&#34; KLF4&#34; -style列与问题无关。在这种情况下,我可能会这样做:

d1[,observation.ID:=.I]
setkey(d1,observation.ID)
d2[,range.ID:=.I]
setkey(d2,range.ID)
d <- CJ(observation.ID=d1[,observation.ID],range.ID=d2[,range.ID])
setkey(d,observation.ID)
d[d1,mid:=i.mid]
setkey(d,range.ID)
d[d2,c("range.low","range.high"):=.(i.range.low,i.range.high)]
d[,falls.in.range:=range.low <= mid & mid <= range.high]

> d
    observation.ID range.ID       mid range.low range.high falls.in.range
 1:              1        1 242601532  11323785   11617177          FALSE
 2:              2        1  85912979  11323785   11617177          FALSE
 3:              3        1  86369900  11323785   11617177          FALSE
 4:              4        1 158289124  11323785   11617177          FALSE
 5:              5        1 123709537  11323785   11617177          FALSE
 6:              6        1   8397351  11323785   11617177          FALSE
 7:              1        2 242601532  12645605   13926923          FALSE
 8:              2        2  85912979  12645605   13926923          FALSE
 9:              3        2  86369900  12645605   13926923          FALSE
10:              4        2 158289124  12645605   13926923          FALSE
11:              5        2 123709537  12645605   13926923          FALSE
12:              6        2   8397351  12645605   13926923          FALSE
13:              1        3 242601532  14750216   15119039          FALSE
14:              2        3  85912979  14750216   15119039          FALSE
15:              3        3  86369900  14750216   15119039          FALSE
16:              4        3 158289124  14750216   15119039          FALSE
17:              5        3 123709537  14750216   15119039          FALSE
18:              6        3   8397351  14750216   15119039          FALSE
19:              1        4 242601532  18102157   19080189          FALSE
20:              2        4  85912979  18102157   19080189          FALSE
21:              3        4  86369900  18102157   19080189          FALSE
22:              4        4 158289124  18102157   19080189          FALSE
23:              5        4 123709537  18102157   19080189          FALSE
24:              6        4   8397351  18102157   19080189          FALSE
25:              1        5 242601532  29491029   30934636          FALSE
26:              2        5  85912979  29491029   30934636          FALSE
27:              3        5  86369900  29491029   30934636          FALSE
28:              4        5 158289124  29491029   30934636          FALSE
29:              5        5 123709537  29491029   30934636          FALSE
30:              6        5   8397351  29491029   30934636          FALSE
31:              1        6 242601532  33716472   35395979          FALSE
32:              2        6  85912979  33716472   35395979          FALSE
33:              3        6  86369900  33716472   35395979          FALSE
34:              4        6 158289124  33716472   35395979          FALSE
35:              5        6 123709537  33716472   35395979          FALSE
36:              6        6   8397351  33716472   35395979          FALSE

(您可以在事后加入其他详细信息列,例如setkey(d,observation.ID);setkey(d1,observation.ID);d[d1,sthg:=i.sthg]以获取&#34; KLF4&#34;列,因为我已将其命名。)但请注意这可能不会节省大量时间;如果你在所有范围内对所有中点进行全面检查,那么加速几乎只在更好的矢量化data.table表达式中,而不是嵌套的for循环。所以我不确定这对你的大桌子来说是否会好得多。也许尝试一下并报告回来?

更新重新输入错误:请参阅下面的示例,以便比较&&(在这种情况下不正确)和&(在这种情况下更正)。正如您所指出的,&&仅评估向量的第一个元素,而&比较向量并返回向量。所以&&的输出被循环使用,当你想要逐行比较时产生不正确的结果:

> d1[,using.double.and:=low < mid && mid==242601532]
> d1[,using.single.and:=low < mid & mid==242601532]
> d1
     chr       low      high sthg       mid observation.ID using.double.and using.single.and
1:  chr1 242601432 242601632 KLF4 242601532              1             TRUE             TRUE
2: chr11  85912879  85913079 CMYC  85912979              2             TRUE            FALSE
3: chr14  86369800  86370000 SOX2  86369900              3             TRUE            FALSE
4:  chr3 158289024 158289224 CMYC 158289124              4             TRUE            FALSE
5:  chr3 123709437 123709637 SOX2 123709537              5             TRUE            FALSE
6:  chr6   8397251   8397451 SOX2   8397351              6             TRUE            FALSE

答案 1 :(得分:2)

在data.table的当前开发版本中使用新的non-equi连接功能,这很简单:

require(data.table) # v1.9.7+
d2[d1, .(mid, sthg), on=.(chr, range.low < mid, range.high > mid), nomatch=0L]

就是这样。在这种情况下,没有匹配。因此返回一个空的data.table。

请参阅devel版本here的安装说明。

PS:我使用过Philip的数据集,但是没有setkey()部分(因为在使用on参数时没有必要)。