[英]Calculating distance between coordinates in different dataframes
假設我有以下兩個數據框
dfA <- data.frame(x = rpois(10,2), y = rpois(10,2), z = rpois(10,2), q = rpois(10,2), t = rpois(10,2))
dfB <- data.frame(x = rpois(10,2), y = rpois(10,2), z = rpois(10,2), q = rpois(10,2), t = rpois(10,2))
dfAB <- map2_df(dfA, dfB, str_c, sep=",") %>%
rename_all(~ str_c('C', seq_along(.)))
dfC <- data.frame(x = rpois(10,2), y = rpois(10,2), z = rpois(10,2), q = rpois(10,2), t = rpois(10,2))
dfD <- data.frame(x = rpois(10,2), y = rpois(10,2), z = rpois(10,2), q = rpois(10,2), t = rpois(10,2))
dfCD <- map2_df(dfC, dfD, str_c, sep=",") %>%
rename_all(~ str_c('C', seq_along(.)))
我要尋找的是找到第一個數據幀和第二個數據幀中坐標之間的距離,所以我得到了第三個數據幀,其中 dfAB 的第一個單元格和 dfCD 的第一個單元格之間的距離,以及 dfAB 的第二個單元格之間的距離以及 dfCD 的第二個單元格,依此類推; 即調用列 C 和行 R,我想要之間的距離
dfAB and dfCD
C1 C2 C... C1 C2 C...
R1 R1 R1 R1
R2 R2 R2 R2
... ... ... ...
etc
我正在尋找的是 dfABC1R1 和 dfCDC1R1、dfABC1R2 和 dfCDC1R2、dfABC2R1 和 dfCDC2R1 等之間的距離。
當我嘗試使用
dist(dfAB,dfCD)
我收到錯誤消息: dist(dfAB,dfCD) 中的錯誤:距離方法無效
任何幫助深表感謝
dist(dfAB, dfCD)
槽錯誤,因為dist()
第二個參數是描述距離計算方法的字符串(例如“歐幾里得”);dfAB
和dfCD
數據框中的坐標元組是字符串。 因此,即使dist()
允許您計算兩個數據幀的每個元素之間的距離,它也會出錯。我的方法不是很優雅,但可能是您可以開始考慮如何處理數據的重點。
set.seed(60007561)
dat <- split(rpois(60, 2), paste0('df_', rep(letters[1:4], each = 15)))
for(i in names(dat)) {
assign(
i,
data.frame(split(dat[[i]], rep(letters[1:5], each = 3)))
)
}
# inspect the data
head(
do.call(
cbind,
lapply(
list(df_a, df_b, df_c, df_d),
cbind,
data.frame(' ' = rep(' ', 3), check.names = F)
)
)
)
# a b c d e a b c d e a b c d e a b c d e
# 1 1 2 1 2 3 0 2 1 2 1 5 0 2 2 0 2 5 2 3 3
# 2 5 0 2 0 3 2 5 1 2 3 0 0 4 2 2 3 1 1 1 2
# 3 3 2 1 3 0 4 2 0 2 2 0 3 1 2 0 2 2 5 1 4
用a...e
列制作兩個小標題,其中每列包含數據框,其中x, y
列對應於來自數據框df_a
, df_b
數據; 和df_c
, df_d
分別。 第一個結果表對應於from points ,第二個 tibble 對應於 points :
df_ab <- as_tibble(lapply(map2(df_a, df_b, ~ list(x = .x, y = .y)), as.data.frame))
df_cd <- as_tibble(lapply(map2(df_c, df_d, ~ list(x = .x, y = .y)), as.data.frame))
#df_ab
# # A tibble: 3 x 5
# a$x $y b$x $y c$x $y d$x $y e$x $y
# <int> <int> <int> <int> <int> <int> <int> <int> <int> <int>
# 1 1 0 2 2 1 1 2 2 3 1
# 2 5 2 0 5 2 1 0 2 3 3
# 3 3 4 2 2 1 0 3 2 0 2
#
#df_cd
# # A tibble: 3 x 5
# a$x $y b$x $y c$x $y d$x $y e$x $y
# <int> <int> <int> <int> <int> <int> <int> <int> <int> <int>
# 1 5 2 0 5 2 2 2 3 0 3
# 2 0 3 0 1 4 1 2 1 2 2
# 3 0 2 3 2 1 5 2 1 0 4
計算從數據到數據之間的歐幾里德距離:
distances <- map2_df(
df_ab,
df_cd,
~ sqrt((.x$x - .y$x)^2 + (.x$y - .y$y)^2)
)
#distances
# # A tibble: 3 x 5
# a b c d e
# <dbl> <dbl> <dbl> <dbl> <dbl>
# 1 4.47 3.61 1.41 1 3.61
# 2 5.10 4 2 2.24 1.41
# 3 3.61 1 5 1.41 2
請注意,上表表示從第一個表中 a...e 列的每個點到第二個表中的相應點的距離
繪制a
列a
距離(以驗證方法,或只是為了好玩):
sgms <- data.frame(
x = df_a$a,
y = df_b$a,
xend = df_c$a,
yend = df_d$a,
l = round(distances$a, 1)
) %>%
mutate(lx = (x + xend) / 2, ly = (y + yend) / 2)
ggplot(data = sgms, aes(x = x, y = y, xend = xend, yend = yend)) +
geom_segment(lty = 3, arrow = arrow(10, ,'closed', ends = 'last')) +
geom_label(aes(x = lx, y = ly, label = l)) +
geom_point(aes(x = x, y = y), pch = 21, size = 3.5) +
geom_text(aes(x = x, y = y, label = sprintf('(%d, %d)', x, y)), vjust = 2) +
geom_point(aes(x = xend, y = yend), pch = 22, size = 3.5) +
geom_text(aes(x = xend, y = yend, label = sprintf('[%d, %d]', xend, yend)), vjust = -2) +
expand_limits(y = c(-.5, 5.5), x = c(-.5, 5.5)) +
ggtitle('Distances btw df_ab, df_cd; col. a') +
ggthemes::theme_tufte()
同意@utubun,在您的示例中使用dist
是一個問題。
dist
有助於計算矩陣中元素之間的距離。 例如:
R> m1 <- matrix(1:8, nrow=4)
R> m1
[,1] [,2]
[1,] 1 5
[2,] 2 6
[3,] 3 7
[4,] 4 8
R> dist(m1)
1 2 3
2 1.414214
3 2.828427 1.414214
4 4.242641 2.828427 1.414214
請注意,行 [1,] 和行 [2,] 之間的歐氏距離為 1.4,這類似於 (1,5) 和 (2,6) 或sqrt(2)
坐標之間的距離。
在您的情況下,您不需要所有點之間的矩陣比較 - 您聽起來對兩個矩陣中坐標對之間的距離最感興趣。
正如@utubun 所提到的,您的坐標需要有數值。 例如,你可以這樣做:
mat1 <- matrix(apply(dfAB, 1:2, function(x) as.numeric(unlist(strsplit(x, ',')))), ncol = 2, byrow = T)
mat2 <- matrix(apply(dfCD, 1:2, function(x) as.numeric(unlist(strsplit(x, ',')))), ncol = 2, byrow = T)
這將為您提供兩個數字矩陣,每個矩陣有 2 列,可以將其視為您的坐標:
R> mat1[1:5,]
[,1] [,2]
[1,] 1 1
[2,] 3 2
[3,] 4 4
[4,] 1 5
[5,] 0 4
R> mat2[1:5,]
[,1] [,2]
[1,] 4 2
[2,] 3 2
[3,] 2 3
[4,] 4 0
[5,] 3 2
要獲得距離,您可以創建一個簡單的函數來計算歐幾里得距離:
euclidean_distance <- function(p, q){
sqrt(sum((p - q)^2))
}
然后通過你的兩個坐標對矩陣按行調用函數:
matrix(sapply(1:nrow(mat1), function(x) euclidean_distance(mat1[x,], mat2[x,])), ncol = 5, byrow = FALSE)
這將為您提供最終的距離矩陣:
[,1] [,2] [,3] [,4] [,5]
[1,] 3.162278 1.000000 4.472136 1.414214 1.414214
[2,] 0.000000 0.000000 2.236068 1.000000 2.000000
[3,] 2.236068 4.472136 5.385165 1.000000 1.000000
[4,] 5.830952 2.236068 4.242641 3.605551 3.605551
[5,] 3.605551 3.162278 1.000000 1.414214 2.000000
[6,] 2.828427 2.000000 2.000000 2.000000 2.236068
[7,] 1.414214 2.236068 2.236068 2.828427 1.414214
[8,] 1.000000 4.000000 2.828427 2.000000 2.000000
[9,] 3.000000 1.000000 1.000000 2.000000 1.000000
[10,] 2.236068 2.828427 4.123106 1.414214 1.000000
數據
set.seed(5)
dfA <- data.frame(x = rpois(10,2), y = rpois(10,2), z = rpois(10,2), q = rpois(10,2), t = rpois(10,2))
dfB <- data.frame(x = rpois(10,2), y = rpois(10,2), z = rpois(10,2), q = rpois(10,2), t = rpois(10,2))
dfAB <- map2_df(dfA, dfB, str_c, sep=",") %>%
rename_all(~ str_c('C', seq_along(.)))
dfC <- data.frame(x = rpois(10,2), y = rpois(10,2), z = rpois(10,2), q = rpois(10,2), t = rpois(10,2))
dfD <- data.frame(x = rpois(10,2), y = rpois(10,2), z = rpois(10,2), q = rpois(10,2), t = rpois(10,2))
dfCD <- map2_df(dfC, dfD, str_c, sep=",") %>%
rename_all(~ str_c('C', seq_along(.)))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.