2012-07-16 105 views
2

我有一個類似下面的表格,其中每個聚類(第1列)包含具有開始(第2列)和結束(第3列)座標的小區域中不同元素(第4列)的註釋。對於每個條目,我想添加一個對應於距離該集羣中最近的其他元素的距離的列。但我想排除羣集中的一對元素具有相同的開始/結束座標或重疊區域的情況。我怎樣才能爲這樣的數據框產生這樣的額外nearest_distance列?如何找到距離最近的非重疊元素的距離?

cluster-47593-walk-0125 252  306  AR  
cluster-47593-walk-0125 6  23  ZNF148 
cluster-47593-walk-0125 357  381  CEBPA 
cluster-47593-walk-0125 263  276  CEBPB 
cluster-47593-walk-0125 246  324  NR3C1 
cluster-47593-walk-0125 139  170  HMGA1 
cluster-47593-walk-0125 139  170  HMGA2 
cluster-47593-walk-0125 207  227  IRF8 
cluster-47593-walk-0125 207  227  IRF1 
cluster-47593-walk-0125 207  245  IRF2 
cluster-47593-walk-0125 207  227  IRF3 
cluster-47593-walk-0125 207  227  IRF4 
cluster-47593-walk-0125 207  227  IRF5 
cluster-47593-walk-0125 207  227  IRF6 
cluster-47593-walk-0125 204  245  IRF7 
cluster-47593-walk-0125 13  36  PATZ1 
cluster-47593-walk-0125 14  143  PAX4 
cluster-47593-walk-0125 4  25  RREB1 
cluster-47593-walk-0125 73  87  SMAD1 
cluster-47593-walk-0125 73  87  SMAD2 
cluster-47593-walk-0125 73  87  SMAD3 
cluster-47593-walk-0125 71  89  SMAD4 
cluster-47593-walk-0125 11  40  SP1 
cluster-47593-walk-0125 11  38  SP2 
cluster-47593-walk-0125 7  38  SP3 
cluster-47593-walk-0125 11  38  SP4 
cluster-47593-walk-0125 13  33  GTF2I 
cluster-47593-walk-0125 281  352  YY1 
cluster-47586-walk-0222 252  306  AR  
cluster-47586-walk-0222 6  23  ZNF148 
[...] 
+0

如果可以保證列2 <=欄3總是,那麼至少可以減少問題檢查符合標準'MAX(數據[條目,3 ]) data [i,3]))'。然後,可能會尋找'哪(min(data [i,2] - selected_data [,3])'等等。 – 2012-07-16 15:27:50

回答

2

首先,一些列名

names(data) <- c("cluster", "start", "end", "element") 
data 
        cluster start end element 
1 cluster-47593-walk-0125 252 306  AR 
2 cluster-47593-walk-0125  6 23 ZNF148 
3 cluster-47593-walk-0125 357 381 CEBPA 
4 cluster-47593-walk-0125 263 276 CEBPB 

現在創建新列

data$nearest_distance <- apply(data, 1, function(x) 
{ 
    cluster <- x[1] 
    start <- as.numeric(x[2]) 
    end <- as.numeric(x[3]) 
    elem <- x[4] 
    posb <- data[data$cluster == cluster & data$element != elem & 
        ((data$start > end) | (data$end < start)), ] 
    startDist <- as.matrix(dist(c(end, posb$start)))[, 1] 
    endDist <- as.matrix(dist(c(start, posb$end)))[, 1] 
    best.dist <- min(startDist[startDist > 0], endDist[endDist > 0]) 
    return(best.dist) 
    } 
) 

我真的不喜歡的功能,至少初期,但我不能來以更好的解決方案..所以我們有

    cluster start end element nearest_distance 
1 cluster-47593-walk-0125 252 306  AR    7 
2 cluster-47593-walk-0125  6 23 ZNF148    48 
3 cluster-47593-walk-0125 357 381 CEBPA    5 
4 cluster-47593-walk-0125 263 276 CEBPB    5 
5 cluster-47593-walk-0125 246 324 NR3C1    1 
..... 

編輯:修復後system.time()測試看來,這是一個非常低效的方法。顯然,這是多餘的計算整個dist()矩陣,所以我們可以在這兩條線路更改爲

startDist <- abs(end-posb$start) 
endDist <- abs(start-posb$end) 

另一個小變化是,我們可以刪除約束data$element != elem因爲後來有> 0。在每個30行的1 000個羣集上測試這個函數需要三分鐘以上。仍然存在子集問題,所以我試圖將數據拆分成一個列表,這允許我們使用矩陣而不是數據框(因爲羣集約束消失) ,這也提高了效率。這一次,我們有10個000簇用30行,每行

data <- data[rep(1:30, each = 10000), ] 
data$cluster <- factor(rep(1:10000, 30)) 

spl <- split(data[, c(2:3)], data$cluster) 
spl <- lapply(spl, data.matrix) 

system.time({ 
x = lapply(spl, function(z) { 
    apply(z, 1, function(x) { 
     start <- x[1] 
     end <- x[2] 
     posb <- z[z[,1] > end | z[,2] < start, , drop = FALSE] 
     startDist <- abs(end-posb[, 1]) 
     endDist <- abs(start-posb[, 2]) 
     best.dist <- min(startDist[startDist > 0], endDist[endDist > 0]) 
     return(best.dist) 
    }) 
    }) 
}) 
data$nearest_distance = unsplit(x, data$cluster) 


user system elapsed 
18.16 0.00 18.35 
+0

看起來不錯+1 – lockedoff 2012-07-16 16:09:53

+0

我有數據集範圍從10e5到10e7條目,它需要相當雖然對我來說,但沒有什麼不可能的。更快會更好:-p – 719016 2012-07-16 22:15:41

+0

@ 130490868091234,你是對的,只是在效率測試中發現一個錯誤,現在我認爲它可以改進.. – Julius 2012-07-16 22:29:53