2012-07-16 71 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