2016-03-01 75 views
1

我採取了一系列的中位數和檢查,看看他們是否在兩者之間的多個區域,然後存儲那些匹配,以及相關聯的標籤的中位數範圍內的值的數據幀跟他們。這段代碼有效,但是對於這種迭代方法來說文件太大了。有沒有做這些比較,並記錄在數據幀的比賽更快的方法?生成落在大型系列範圍

的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) 
+0

如果你給了我們'tfile'和'ranges'的結構,而不是告訴我們他們從txt文件中讀取(不相關),那將會很棒。請參閱[如何編寫一個偉大的R可重現的例子](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) – C8H10N4O2

+0

編輯的問題,希望有更多的可讀性。 – Satchmo

+0

你能準確解釋你想知道的信息嗎?在我看來,(a)你想知道,對於每個範圍,每個*中位數是否落在該範圍內,(b)只有當「chr」列匹配時,每個*中位數是否落在該範圍內,或(c)其他事物,例如只有一行一行是否給定的行與另一個表中的給定範圍相匹配,等等......? – Philip

回答

2

請參閱我的評論--I'm不知道你想要做什麼,但它似乎有一個data.table j的味道OIN。我複製你的表作爲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?data.table可能allow.cartesian

編輯如果你真的意思是你要知道每一個範圍內的每個中點是否落在範圍內,那麼,你是在交叉聯接領土。注意,這意味着你基本上是考慮「CHR 1」式和「KLF4」式列是無關的問題。在這種情況下,我可能會做這樣的事情:

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]獲得「KLF4」列我命名它。)但是請注意, 這可能不會節省大量的時間;如果你做對所有範圍內的所有中點的全面檢查,然後加速是相當多隻有在更好的向量化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 
+0

經過一些修補你的建議後,它的工作!儘管如此,我擔心絕對沒有任何一箇中鋒會在這個範圍內。 – Satchmo

+1

運行您的for循環時,您是否在任何範圍內都獲得了mids?縱觀示例數據,它看起來並不像任何數據,但如果生命取決於答案,則可能需要更仔細地檢查。 – Philip

+1

經過一些測試後,似乎只有第一行是中間值與範圍進行比較的位置。有沒有辦法將這個應用到每一行而不使用for循環? – Satchmo

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。

請參閱開發版here的安裝說明。 PS:我已經使用了菲利普的數據集,但沒有使用setkey()部分(因爲在使用on參數時沒有必要)。