Return 两个数据帧中两个长纬度坐标的每行和每列之间的最小距离
Return minimum distance between each row and each column of two long lat coordinates in two dataframes
我想计算两个数据帧的每一行和每一列之间的最小地理距离。
DF1有很多机构,DF2有很多赛事。喜欢,所以:
#DF1 (institutions)
DF1 <- data.frame(latitude=c(41.49532, 36.26906, 40.06599),
longitude=c(-98.77298, -101.40585, -80.72291))
DF1$institution <- letters[seq( from = 1, to = nrow(DF1))]
#DF2 (events)
DF2 <- data.frame(latitude=c(32.05, 32.62, 30.23), longitude=c(-86.82,
-87.67, -88.02))
DF2$ID <- seq_len(nrow(DF1)
我想return将DF1中每个机构距离最近的事件,把DF2的距离和ID都加到DF1上。虽然我知道如何计算成对距离,但我无法计算从 DF[1,] 到 DF2 和 return 最小值等的所有距离。
这是我尝试过的(但失败了)。
library(geosphere)
#Define a function
distanceCALC <- function(x, y) { distm(x = x, y = y,
fun = distHaversine)}
#Define vector of events
DF2_vec <- DF2[, c('longitude', 'latitude')]
#Define df to hold distances
shrtdist <- data.frame()
现在,我的尝试是将 DF1 的第 1 行和矢量化事件提供给 distanceCALC。
#Loop through every row in DF1 and calculate all the distances to instutions a, b, c. Append to DF1 smallest distance + DF2$ID.
#This only gives me the pairwise distance
for (i in nrow(DF1)){
result <- distanceCALC(DF1[i,c('longitude', 'latitude')], DF2_vec)
}
#Somehow take shortest distance for each row*column distance matrix
shrtdist <- rbind(shrtdist, min(result[,], na.rm = T))
我的猜测是解决方案需要重塑数据和 lapply。此外,循环是非常糟糕的做法,考虑到观察次数,循环速度太慢。
非常感谢任何帮助。
这是使用 outer
函数
解决此问题的简单方法
squared_distance <- function(x, y ) (x - y)^2
lat <- outer(DF1$latitude, DF2$latitude, squared_distance)
long <- outer(DF1$longitude, DF2$longitude, squared_distance)
pairwise_dist <- sqrt(lat + long)
rownames(pairwise_dist) <- DF1$institution
colnames(pairwise_dist) <- DF2$ID
pairwise_dist
这为您提供了每个机构(行)和事件(列)之间距离的矩阵。要获取 df1 中的距离和事件,我们可以这样做
df1$min_dist <- apply(pairwise_dist, 1, min)
df1$min_inst <- apply(pairwise_dist, 1, min)
请注意,第二个在这种情况下起作用的原因是事件是用数字标记的。如果你的真实数据没有这个方便的功能,我们需要做
df1$min_inst <- colnames(pairwise_dist)[apply(pairwise_dist, 1, which.min)]
使用替代距离函数更新
我还没有对此进行测试,但我认为这应该可行。同样,输出将是一个矩阵。
gcd.hf <- function(DF1, DF2) {
sin2.long <- sin(outer(DF1$longitude, DF2$longitude, "-") / 2)^2
sin2.lat <- outer(DF1$latitude, DF2$latitude, "-")
cos.lat <- outer(cos(DF1$latitude), cos(DF2$latitude), "*")
a <- sin2.long + sin2.lat * cos.lat # we do this cell-wise
cir <- 2 * asin(pmin(1, sqrt(a))) # I never assign anything to "c" since that's concatenate. Rename this variable as appropriate (I have no idea if it's related to the circumference or not.)
cir * 6371
}
pairwise_dist <- gcd.hf(DF1, DF2)
我想计算两个数据帧的每一行和每一列之间的最小地理距离。 DF1有很多机构,DF2有很多赛事。喜欢,所以:
#DF1 (institutions)
DF1 <- data.frame(latitude=c(41.49532, 36.26906, 40.06599),
longitude=c(-98.77298, -101.40585, -80.72291))
DF1$institution <- letters[seq( from = 1, to = nrow(DF1))]
#DF2 (events)
DF2 <- data.frame(latitude=c(32.05, 32.62, 30.23), longitude=c(-86.82,
-87.67, -88.02))
DF2$ID <- seq_len(nrow(DF1)
我想return将DF1中每个机构距离最近的事件,把DF2的距离和ID都加到DF1上。虽然我知道如何计算成对距离,但我无法计算从 DF[1,] 到 DF2 和 return 最小值等的所有距离。
这是我尝试过的(但失败了)。
library(geosphere)
#Define a function
distanceCALC <- function(x, y) { distm(x = x, y = y,
fun = distHaversine)}
#Define vector of events
DF2_vec <- DF2[, c('longitude', 'latitude')]
#Define df to hold distances
shrtdist <- data.frame()
现在,我的尝试是将 DF1 的第 1 行和矢量化事件提供给 distanceCALC。
#Loop through every row in DF1 and calculate all the distances to instutions a, b, c. Append to DF1 smallest distance + DF2$ID.
#This only gives me the pairwise distance
for (i in nrow(DF1)){
result <- distanceCALC(DF1[i,c('longitude', 'latitude')], DF2_vec)
}
#Somehow take shortest distance for each row*column distance matrix
shrtdist <- rbind(shrtdist, min(result[,], na.rm = T))
我的猜测是解决方案需要重塑数据和 lapply。此外,循环是非常糟糕的做法,考虑到观察次数,循环速度太慢。
非常感谢任何帮助。
这是使用 outer
函数
squared_distance <- function(x, y ) (x - y)^2
lat <- outer(DF1$latitude, DF2$latitude, squared_distance)
long <- outer(DF1$longitude, DF2$longitude, squared_distance)
pairwise_dist <- sqrt(lat + long)
rownames(pairwise_dist) <- DF1$institution
colnames(pairwise_dist) <- DF2$ID
pairwise_dist
这为您提供了每个机构(行)和事件(列)之间距离的矩阵。要获取 df1 中的距离和事件,我们可以这样做
df1$min_dist <- apply(pairwise_dist, 1, min)
df1$min_inst <- apply(pairwise_dist, 1, min)
请注意,第二个在这种情况下起作用的原因是事件是用数字标记的。如果你的真实数据没有这个方便的功能,我们需要做
df1$min_inst <- colnames(pairwise_dist)[apply(pairwise_dist, 1, which.min)]
使用替代距离函数更新
我还没有对此进行测试,但我认为这应该可行。同样,输出将是一个矩阵。
gcd.hf <- function(DF1, DF2) {
sin2.long <- sin(outer(DF1$longitude, DF2$longitude, "-") / 2)^2
sin2.lat <- outer(DF1$latitude, DF2$latitude, "-")
cos.lat <- outer(cos(DF1$latitude), cos(DF2$latitude), "*")
a <- sin2.long + sin2.lat * cos.lat # we do this cell-wise
cir <- 2 * asin(pmin(1, sqrt(a))) # I never assign anything to "c" since that's concatenate. Rename this variable as appropriate (I have no idea if it's related to the circumference or not.)
cir * 6371
}
pairwise_dist <- gcd.hf(DF1, DF2)