2014-10-10 81 views
2

假设我有点的坐标,每个ID。我如何sdhould提取德劳内三角距离列出对象中的R?如何提取德劳内三角距离列出对象中的R

# My data are similar to this structure 
id <- c("A","B","C","D","E","F","G","H","I","J","K","L","M","N") 
x_coor <- c(0.5,1,1,1.5,2,3,3,3.5,4,4.5,5,5,6,7) 
y_coor <- c(5.5,3,7,6.5,5,3.5,3,1.5,1,2.5,4,5,3.5,5.5) 
my.data <- data.frame(id = id, x_coor = x_coor, y_coor = y_coor) 

# When I perform Delaunay triangulation, I can see the distances.... 
library(tripack) 
my.triangles<-tri.mesh(my.data$x_coor, my.data$y_coor) 
plot(my.triangles, do.points=FALSE, lwd=0.2) 
points(my.data$x, my.data$y, col = "black", pch=20, cex = 1.5) 
text(my.data$x, my.data$y, labels = my.data$id) 

enter image description here

我怎样才能提取点的 “双” 列出对象也是这样吗?

# I need something like this... 
my.list 
[[A]] 
[1] 2.55 1.58 1.41 1.58 (all distances connected to "A") 
[[B]] 
[1] 2.55 2.24 2.06 2.00 2.92 3.61 (all distances connected to "B") 
etc. 

回答

3

开始在tri.mesh()

my_triangles <- tri.mesh(my.data$x_coor, my.data$y_coor) 
plot(my_triangles, do.points=FALSE, lwd=0.2) 

str(my_triangles)?neighbours的R文件,我们可以通过对每个点提取邻居如下进行:

neiblist <- neighbours(my_triangles) 

然后从原始数据框中追加点ID,这样你几乎有你想要的清单,除了它包含邻居的ID,而不是距离:

names(neiblist) <- my.data$id   #append names for later reference 

然后计算与欧氏距离矩阵所有的点:

euc_dist <- as.matrix(dist(cbind(x=my_triangles$x, y=my_triangles$y))) 

#Append dimnames for reference 

colnames(euc_dist) <- my.data$id 
rownames(euc_dist) <- my.data$id 

找到一个点可能有最大的邻国:所需的内存预分配

max_n <- max(unlist(lapply(neiblist, length))) 
npoints <- length(my.data$id)     # This is just the total number of points 

预分配的内存中收集结果,重要的计算效率和速度

dist_2neigh_mat <- matrix(nrow=npoints, ncol=max_n) #Create results matrix 

rownames(dist_2neigh_mat) <- my.data$id 
colnames(dist_2neigh_mat) <- colnames(data.frame(dist=matrix(data=1:6, nrow=1))) 

获取和收集距离向量所有点。

for (i in my.data$id){ 
neighbors_i <- neiblist[[i]] 
dist2neighbours_i <- euc_dist[,i][neighbors_i] 

#Append vector with NAs to match ncol of results matrix 

dist2neighbours_i <- c(dist2neighbours_i, rep(NA, 
times=(max_n-length(dist2neighbours_i)))) 

dist_2neigh_mat[i,] <- dist2neighbours_i #Update results matrix with i'th distances 
} 

dist_2neigh_mat包含您的结果。如果你坚持在具有完全按照您的问题声明列表中的结果,然后你只需要结果矩阵转换为这样的列表如下:

results_list <- as.list(data.frame(t(dist_2neigh_mat))) 

然后,您可以摆脱先前生成的NA的与基质完整性方面的原因:

#Function to remove NA's 

fun_NA <- function(x){x=x[!is.na(x)] 
return(x)} 

取下结果

NA的
results_list <- lapply(results_list, FUN=fun_NA) 

我的想法是,这将是非常非常迅速的,甚至有很多很多p0的ts ..但有人可能知道不同:-)

干杯。

+0

伟大的工作@Shekeine!非常感谢计算效率和速度。 – 2014-10-10 21:26:52

+0

当然,不是问题:-) – shekeine 2014-10-10 21:45:22

1

连接到“A”的所有分段的一个端点等于坐标“A”。查找这些坐标:

xy<- c(x-coor[id=='A'],y_coor[id=='A']) 

如果你再做,例如,print.tri(my.triangles),你会得到一个邻接打印:

#partial result 
    triangulation nodes with neigbours: 
    node: (x,y): neighbours 
    1: (0.5,5.5) [4]: 2 3 4 5 
    2: (1,3) [6]: 1 5 6 7 8 9 
    3: (1,7) [3]: 1 4 14 

通过观察xy值匹配在此打印输出的第一个坐标,您可以抓住相邻的顶点并查找它们的坐标。这可能更容易执行

my_neighbor<-neighbours(my.triangles) 
# partial result: 
[[1]] 
[1] 2 3 4 5 

[[2]] 
[1] 1 5 6 7 8 9 

[[3]] 
[1] 1 4 14 

[[4]] 
[1] 1 3 5 12 14 

然后只是抓住坐标。例如。对于第一个顶点,邻居是2,3,4,5。抓住坐标xtmp<- my.triangles$x[c(1,2:5)]ytmp<-my.triangles$y[c(1,2:5)],建立一个矩阵,并产生距离:

dist(cbind(xtmp,ytmp)) 

第一列的结果是你想要的,我们有距离,为您my.list$A

+0

嗨@CarlWitthotf。谢谢您的回答。但上面的数据只是我整个数据集中的一个片段。我有超过1 000个点,因此需要很长时间分别为每个点提取距离。是否有可能修改你的答案以更好地适应这种情况? – 2014-10-10 15:14:51

+0

@LadislavNado如果我有时间,我会这样做的,但是你应该能够接受我提出的离散操作,并在它们周围编写一些for循环来自动化整个事情。 – 2014-10-10 16:21:18

+0

好吧,我试着做一些循环。非常感谢;) – 2014-10-10 16:45:58