2012-07-16 2 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 열은 항상 다음 적어도 당신이 기준'최대 (데이터를 [충족 항목을 검사에 문제를 줄일 수 있습니다, 3 10 개 000 클러스터가 ]) data [i, 3]))'이다. –

답변

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() 매트릭스를 전체 계산할 중복, 그래서 우리는 또 다른 작은 변화가 나중에 > 0이 있기 때문에 우리는 제약을 data$element != elem을 삭제할 수 있다는 것입니다

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

이 두 줄을 변경할 수 있습니다. 하위 집합 문제가 남아 있으므로 데이터를 목록으로 분할하려고 했으므로 데이터 프레임 대신 행렬을 사용할 수 있습니다 (클러스터 제약 조건이 사라짐). , 효율성도 향상됩니다. 이 시간 우리는 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

+0

데이터 세트가 10e5에서 10e7 항목까지 있으며, 꽤 많은 수의 데이터가 필요합니다 (예 : 데이터 (i, 2) - selected_data [, 3]). 나를 위해,하지만 불가능한 것은 없습니다. 더 빠를수록 좋을 것입니다 :-p – 719016

+0

@ 130490868091234, 당신이 옳았습니다, 그냥 효율성 테스트에서 실수를 발견하고 지금은 개선 될 수 있다고 생각합니다. – Julius

관련 문제