Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/74.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 数据帧中任意点之间的唯一成对距离_R_Dplyr_Euclidean Distance - Fatal编程技术网

R 数据帧中任意点之间的唯一成对距离

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) #

我有一张十点的列表,上面有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) 

# 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