R 数据帧中任意点之间的唯一成对距离
我有一张十点的列表,上面有X和Ỳ 协调。我想计算任意两点之间距离的可能排列。准确地说,只有1-2,2-1中的一个距离应该存在。我已经设法消除了一个点与它自身的距离。但无法实现这种排列距离R 数据帧中任意点之间的唯一成对距离,r,dplyr,euclidean-distance,R,Dplyr,Euclidean Distance,我有一张十点的列表,上面有X和Ỳ 协调。我想计算任意两点之间距离的可能排列。准确地说,只有1-2,2-1中的一个距离应该存在。我已经设法消除了一个点与它自身的距离。但无法实现这种排列距离 # Data Generation df <- data.frame(X = runif(10, 0, 1), Y = runif(10, 0, 1), ID = 1:10) # Temporary key Creation df <- df %>% mutate(key = 1) #
# Data Generation
df <- data.frame(X = runif(10, 0, 1), Y = runif(10, 0, 1), ID = 1:10)
# Temporary key Creation
df <- df %>% mutate(key = 1)
# Calculating pairwise distances
df %>% full_join(df, by = "key") %>%
mutate(dist = sqrt((X.x - X.y)^2 + (Y.x - Y.y)^2)) %>%
select(ID.x, ID.y, dist) %>% filter(!dist == 0) %>% head(11)
# Output
# ID.x ID.y dist
# 1 1 2 0.90858911
# 2 1 3 0.71154587
# 3 1 4 0.05687495
# 4 1 5 1.03885510
# 5 1 6 0.93747717
# 6 1 7 0.62070415
# 7 1 8 0.88351690
# 8 1 9 0.89651911
# 9 1 10 0.05079906
# 10 2 1 0.90858911
# 11 2 3 0.27530175
但是这种方法在计算上比dist慢。如果听更快的方法,我会更高兴。我会对数据使用dist,然后将输出处理成所需的格式。您可以用任何其他距离函数替换dist。在这里,我使用字母而不是数字作为ID来更好地显示正在发生的事情
set.seed(42)
df <- data.frame(X = runif(10, 0, 1), Y = runif(10, 0, 1), ID = letters[1:10])
df %>%
column_to_rownames("ID") %>% #make the ID the rownames. dist will use these> NB will not work on a tibble
dist() %>%
as.matrix() %>%
as.data.frame() %>%
rownames_to_column(var = "ID.x") %>% #capture the row IDs
gather(key = ID.y, value = dist, -ID.x) %>%
filter(ID.x < ID.y) %>%
as_tibble()
# A tibble: 45 x 3
ID.x ID.y dist
<chr> <chr> <dbl>
1 a b 0.2623175
2 a c 0.7891034
3 b c 0.6856994
4 a d 0.2191960
5 b d 0.4757855
6 c d 0.8704269
7 a e 0.2730984
8 b e 0.3913770
9 c e 0.5912681
10 d e 0.2800021
# ... with 35 more rows
与通过计算距离进行循环相比,dist速度非常快。
通过直接处理dist对象而不是将其转换为矩阵,代码可能会变得更高效。我会对数据使用dist,然后将输出处理为所需的格式。您可以用任何其他距离函数替换dist。在这里,我使用字母而不是数字作为ID来更好地显示正在发生的事情
set.seed(42)
df <- data.frame(X = runif(10, 0, 1), Y = runif(10, 0, 1), ID = letters[1:10])
df %>%
column_to_rownames("ID") %>% #make the ID the rownames. dist will use these> NB will not work on a tibble
dist() %>%
as.matrix() %>%
as.data.frame() %>%
rownames_to_column(var = "ID.x") %>% #capture the row IDs
gather(key = ID.y, value = dist, -ID.x) %>%
filter(ID.x < ID.y) %>%
as_tibble()
# A tibble: 45 x 3
ID.x ID.y dist
<chr> <chr> <dbl>
1 a b 0.2623175
2 a c 0.7891034
3 b c 0.6856994
4 a d 0.2191960
5 b d 0.4757855
6 c d 0.8704269
7 a e 0.2730984
8 b e 0.3913770
9 c e 0.5912681
10 d e 0.2800021
# ... with 35 more rows
与通过计算距离进行循环相比,dist速度非常快。
通过直接处理dist对象而不是将其转换为矩阵,代码可能会变得更高效。也许这是一种稍微简单的方法:
df <- data.frame(X = runif(10, 0, 1), Y = runif(10, 0, 1), ID = 1:10)
df2 <- data.frame(ID1 = rep(1:10, each = 10),
ID2 = 1:10,
distance = as.vector(as.matrix((dist(df)))))
然后去掉对角线:
df2 <- df2[df2$ID1 != df2$ID2,]
去掉上面的三角形:
df2 <- df2[df2$ID1 < df2$ID2,]
df2
ID1 ID2 distance
2 1 2 1.000615
3 1 3 2.057813
4 1 4 3.010261
5 1 5 4.039502
6 1 6 5.029982
7 1 7 6.035427
8 1 8 7.012540
9 1 9 8.006249
10 1 10 9.015352
13 2 3 1.099245
14 2 4 2.011664
...
也许这是一种稍微简单的方法:
df <- data.frame(X = runif(10, 0, 1), Y = runif(10, 0, 1), ID = 1:10)
df2 <- data.frame(ID1 = rep(1:10, each = 10),
ID2 = 1:10,
distance = as.vector(as.matrix((dist(df)))))
然后去掉对角线:
df2 <- df2[df2$ID1 != df2$ID2,]
去掉上面的三角形:
df2 <- df2[df2$ID1 < df2$ID2,]
df2
ID1 ID2 distance
2 1 2 1.000615
3 1 3 2.057813
4 1 4 3.010261
5 1 5 4.039502
6 1 6 5.029982
7 1 7 6.035427
8 1 8 7.012540
9 1 9 8.006249
10 1 10 9.015352
13 2 3 1.099245
14 2 4 2.011664
...
您可能需要将filterID.x