2

我有一个如下表所示的表格,其中每个集群(第 1 列)包含小区域中不同元素(第 4 列)的注释,具有起始(第 2 列)和结束(第 3 列)坐标。对于每个条目,我想添加一列,该列对应于到该集群中最近的其他元素的距离。但我想排除集群中的一对元素具有相同的开始/结束坐标或重叠区域的情况。我怎样才能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()矩阵 是多余的,所以我们可以将这两行改为

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

另一个小的变化是我们可以删除约束data$element != elem,因为后面有> 0. 在 1000 个集群上测试这个函数,每个集群有 30 行,耗时超过三分钟。仍然存在子集问题,所以我尝试将数据拆分为一个列表,这允许我们使用矩阵而不是数据框(因为集群的约束消失了) ,这也提高了效率。这次我们有 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 
于 2012-07-16T15:42:07.500 回答