r - 如何找到到最近的非重叠元素的距离?

标签 r dataframe

我有一个如下表所示的表,其中每个簇(第 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
[...]

最佳答案

首先,一些列名称

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 

关于r - 如何找到到最近的非重叠元素的距离?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11505625/

相关文章:

python - Python中的频繁模式挖掘

html - Rshiny - 将 slider 与文本输入相结合,使 slider 更加人性化

python - SQL "partition by"Python/R 中的类似功能

r - 使用 ggplot2 的直方图中心条

python - 如何根据行值合并两个大小不等的DataFrame

r - 从数据框中选择偶数天

r - 按两列分组并汇总多列

python - 如何在python或R中统一生成半圆内的一组随机点?

rmarkdown : kable, Word 文档中的 xtable 或 tab_df 表

python - Pandas 中的多维/嵌套 DataFrame/Dataset/Panel