我有一个包含以下列的数据表:
name, x, y
a, 1, 2
b, 2, 3
c, 3, 1
我想将这个表与自身连接起来,保留 name != name
的每一行,并在 x
和 y
上运行一个距离函数> 每一方的值(value)。结果应采用以下格式:
name1, name2, distance
我这样写距离函数:
dist <- function(a, b) sqrt((a$x-b$x)^2 + (a$y-b$y)^2)
我尝试使用 outer
函数,但它只接受向量,而不接受数据表,我尝试使用 dplyr 中的各种连接但没有成功。
最佳答案
假设您的数据集如下所示:
d <- data_frame(name = rownames(mtcars), x = mtcars$mpg, y = mtcars$cyl)
尝试两个数据框的所有组合(或它们自身的所有组合)的一般方法是 tidyr 的 crossing
函数(尽管您需要小心重命名列)。之后您将能够计算距离并进行过滤:
library(dplyr)
library(tidyr)
d %>%
rename(name1 = name, x1 = x, y1 = y) %>%
crossing(d) %>%
rename(name2 = name, x2 = x, y2 = y) %>%
mutate(distance = sqrt((x1 - x2) ^ 2 + (y1 - y2) ^ 2)) %>%
filter(name1 != name2)
在这种特殊情况下,您可以使用我的 fuzzyjoin包,特别是 distance_join
(您需要 GitHub 的最新开发版本)。这将根据距离阈值连接两个数据帧(在本例中为自连接),并附加一个带有距离的附加列:
library(fuzzyjoin)
d %>%
rename(name1 = name) %>%
distance_inner_join(d, max_dist = Inf, distance_col = "distance") %>%
rename(name2 = name) %>%
filter(name1 != name2)
这将给出:
# A tibble: 992 x 7
name1 x.x y.x name2 x.y y.y distance
<chr> <dbl> <dbl> <chr> <dbl> <dbl> <dbl>
1 Mazda RX4 21 6 Mazda RX4 Wag 21.0 6 0.000000
2 Mazda RX4 21 6 Datsun 710 22.8 4 2.690725
3 Mazda RX4 21 6 Hornet 4 Drive 21.4 6 0.400000
4 Mazda RX4 21 6 Hornet Sportabout 18.7 8 3.047950
5 Mazda RX4 21 6 Valiant 18.1 6 2.900000
6 Mazda RX4 21 6 Duster 360 14.3 8 6.992138
7 Mazda RX4 21 6 Merc 240D 24.4 4 3.944617
8 Mazda RX4 21 6 Merc 230 22.8 4 2.690725
9 Mazda RX4 21 6 Merc 280 19.2 6 1.800000
10 Mazda RX4 21 6 Merc 280C 17.8 6 3.200000
# ... with 982 more rows
如果您知道自己不关心远距离匹配,则可以将 max_dist
设置为另一个非无限阈值。
关于R数据表外连接按功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38667406/