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
[...]
4

1 に答える 1

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()行列全体を計算するのは冗長なので、これらの2行を次のように変更できます。

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

もう1つの小さな変更は、data$element != elem後であるため、制約を削除できることです> 0。それぞれ30行の1000クラスターでこの関数をテストするには3分以上かかりました。サブセット化の問題が残っているため、データをリストに分割しようとしました。これにより、データフレームの代わりに行列を使用できるようになります(クラスターの制約がなくなるため) 、これも効率を向上させます。今回は、それぞれ30行の10000個のクラスターがあります。

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 
于 2012-07-16T15:42:07.500 に答える