我有一个类似下面的表,其中每个聚类(第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
[...]
答案 0 :(得分: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
。在1 000个簇上测试这个函数,每个30行,每个花费超过3分钟。仍然存在子集问题,所以我尝试将数据拆分成列表,这允许我们使用矩阵而不是数据帧(因为簇的约束消失了) ,这也提高了效率。这次我们有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