R:计算从一个点到另一个点的距离(以英里为单位)
R: Calculating distance in miles from one point to another
我有以下数据框:
library(dplyr)
d1 <- data_frame(
title = c("base1", "base2", "base3", "base4"),
lat = c(57.3, 58.8, 47.2, 57.8),
long = c(0.4, 3.4, 3.5, 1.2))
d2 <- data_frame(
tas = c("tas1", "tas2", "tas3", "tas4"),
Base= c ("base1", "base2", "base3", "base4"),
lat=c(54.6, 56.4, 54.2, 54.6),
long = c(1.2, 3.4, 3.5, 56.6))
我想做的是计算 d2 中的 tas 和 d1 中的 title 之间的距离(以英里为单位)。所以在 d2 中,tas1 的坐标为 54.6 lat 和 1.2 long,并且在 'Base' 列中有 'base1'。所以我想计算 54.6lat 乘 1.2long 与 57.3lat 和 0.4lon 之间的距离。
我已尝试使用 GeoDistanceInMetresMatrix
函数来执行此操作,详见下文,但该函数并没有完全提供我想要的结构。
下面的文章提供了一些关于 GeoDistanceInMetresMatrix 的信息
http://eurekastatistics.com/calculating-a-distance-matrix-for-geographic-points-using-r/
这是我希望数据的样子:
df <- data_frame(
tas = c("tas1", "tas2", "tas3", "tas4"),
Base= c ("base1", "base2", "base3", "base4"),
lat=c(54.6, 56.4, 54.2, 54.6),
long = c(1.2, 3.4, 3.5, 56.6),
difference_miles = c(23, 35, 56, 23))
我整个下午都在看这个,但不太明白,所以我们将不胜感激!
这可以使用 geosphere 库轻松完成:
d1 <- data.frame(
title = c("base1", "base2", "base3", "base4"),
lat = c(57.3, 58.8, 47.2, 57.8),
long = c(0.4, 3.4, 3.5, 1.2))
d2 <- data.frame(
tas = c("tas1", "tas2", "tas3", "tas4"),
Base= c ("base1", "base2", "base3", "base4"),
lat=c(54.6, 56.4, 54.2, 54.6),
long = c(1.2, 3.4, 3.5, 56.6))
library(geosphere)
#1609.35 is the conversion from miles to meters
dist<-distGeo(d1[, c("long", "lat")], d2[, c("long", "lat")])/1609.35
df<-cbind(d2, difference_miles=dist)
一种方法可能是使用 geosphere
包:
# slightly modify your data because I want to merge it
df1 <- data.frame(
title = c("base1", "base2", "base3", "base4"),
lat1 = c(57.3, 58.8, 47.2, 57.8),
long1 = c(0.4, 3.4, 3.5, 1.2),
stringsAsFactors = FALSE)
df2 <- data.frame(
title = c ("base1", "base2", "base3", "base4"),
lat2 = c(54.6, 56.4, 54.2, 54.6),
long2 = c(1.2, 3.4, 3.5, 56.6),
stringsAsFactors = FALSE)
# merge your data so you're sure your lat/long pairs make sense
df <- merge(df1, df2, by="title")
# calculate distance according to the Haversine method (shortest dist around sphere)
df$dist_meters <- geosphere::distHaversine(
p1=df[ , c("long1", "lat1")],
p2=df[ , c("long2", "lat2")] )
# convert meters to miles
df$dist_miles = df$dist_meters / 1609.34
您还应该查看 sp
library(sp)
p1 <- SpatialPoints(select(d1, long, lat))
p2 <- SpatialPoints(select(d2, long, lat))
spDists(p1, p2, longlat=TRUE, diagonal=TRUE)
# [1] 304.7427 267.2908 778.7028 3359.7988 (output is km)
由于您已经在使用 dplyr
,因此您可以轻松地将 sf
添加到您的工作流程中。在这里,我使用 long/lat 坐标和 long/lat 投影将您的数据框制作成具有 sf
列的数据框。然后,我将它们分别转换为以美国脚为基础的投影并计算距离。如果需要,您可以将该距离向量添加到两个初始数据帧的连接版本中。
要注意的一个注意事项是顺序——我按基本标签排列 d1_sf
和 d2_sf
,但如果这在更大或更复杂的数据集中效果不佳,或者有缺失的碱基,你可以在这里使用连接来检查。
library(tidyverse)
library(sf)
...
d1_sf <- st_as_sf(d1, coords = c("long", "lat"), crs = 4326) %>%
arrange(title)
d2_sf <- st_as_sf(d2, coords = c("long", "lat"), crs = 4326) %>%
arrange(Base)
distances <- st_distance(
st_transform(d1_sf, crs = 2234),
st_transform(d2_sf, crs = 2234),
by_element = T
)
distances
#> Units: US_survey_foot
#> [1] 1035387.8 916425.4 2591457.0 11553291.3
inner_join(d1, d2, by = c("title" = "Base"), suffix = c("1", "2")) %>%
mutate(dist = distances) %>%
mutate(dist_mi = dist / 5280)
#> # A tibble: 4 x 8
#> title lat1 long1 tas lat2 long2 dist dist_mi
#> <chr> <dbl> <dbl> <chr> <dbl> <dbl> <S3: units> <S3: units>
#> 1 base1 57.3 0.4 tas1 54.6 1.2 " 1035387.8 US_su… " 196.0962 US_su…
#> 2 base2 58.8 3.4 tas2 56.4 3.4 " 916425.4 US_su… " 173.5654 US_su…
#> 3 base3 47.2 3.5 tas3 54.2 3.5 " 2591457.0 US_su… " 490.8062 US_su…
#> 4 base4 57.8 1.2 tas4 54.6 56.6 11553291.3 US_sur… 2188.1234 US_sur…
由 reprex package (v0.2.0) 创建于 2018-08-13。
我有以下数据框:
library(dplyr)
d1 <- data_frame(
title = c("base1", "base2", "base3", "base4"),
lat = c(57.3, 58.8, 47.2, 57.8),
long = c(0.4, 3.4, 3.5, 1.2))
d2 <- data_frame(
tas = c("tas1", "tas2", "tas3", "tas4"),
Base= c ("base1", "base2", "base3", "base4"),
lat=c(54.6, 56.4, 54.2, 54.6),
long = c(1.2, 3.4, 3.5, 56.6))
我想做的是计算 d2 中的 tas 和 d1 中的 title 之间的距离(以英里为单位)。所以在 d2 中,tas1 的坐标为 54.6 lat 和 1.2 long,并且在 'Base' 列中有 'base1'。所以我想计算 54.6lat 乘 1.2long 与 57.3lat 和 0.4lon 之间的距离。
我已尝试使用 GeoDistanceInMetresMatrix
函数来执行此操作,详见下文,但该函数并没有完全提供我想要的结构。
下面的文章提供了一些关于 GeoDistanceInMetresMatrix 的信息
http://eurekastatistics.com/calculating-a-distance-matrix-for-geographic-points-using-r/
这是我希望数据的样子:
df <- data_frame(
tas = c("tas1", "tas2", "tas3", "tas4"),
Base= c ("base1", "base2", "base3", "base4"),
lat=c(54.6, 56.4, 54.2, 54.6),
long = c(1.2, 3.4, 3.5, 56.6),
difference_miles = c(23, 35, 56, 23))
我整个下午都在看这个,但不太明白,所以我们将不胜感激!
这可以使用 geosphere 库轻松完成:
d1 <- data.frame(
title = c("base1", "base2", "base3", "base4"),
lat = c(57.3, 58.8, 47.2, 57.8),
long = c(0.4, 3.4, 3.5, 1.2))
d2 <- data.frame(
tas = c("tas1", "tas2", "tas3", "tas4"),
Base= c ("base1", "base2", "base3", "base4"),
lat=c(54.6, 56.4, 54.2, 54.6),
long = c(1.2, 3.4, 3.5, 56.6))
library(geosphere)
#1609.35 is the conversion from miles to meters
dist<-distGeo(d1[, c("long", "lat")], d2[, c("long", "lat")])/1609.35
df<-cbind(d2, difference_miles=dist)
一种方法可能是使用 geosphere
包:
# slightly modify your data because I want to merge it
df1 <- data.frame(
title = c("base1", "base2", "base3", "base4"),
lat1 = c(57.3, 58.8, 47.2, 57.8),
long1 = c(0.4, 3.4, 3.5, 1.2),
stringsAsFactors = FALSE)
df2 <- data.frame(
title = c ("base1", "base2", "base3", "base4"),
lat2 = c(54.6, 56.4, 54.2, 54.6),
long2 = c(1.2, 3.4, 3.5, 56.6),
stringsAsFactors = FALSE)
# merge your data so you're sure your lat/long pairs make sense
df <- merge(df1, df2, by="title")
# calculate distance according to the Haversine method (shortest dist around sphere)
df$dist_meters <- geosphere::distHaversine(
p1=df[ , c("long1", "lat1")],
p2=df[ , c("long2", "lat2")] )
# convert meters to miles
df$dist_miles = df$dist_meters / 1609.34
您还应该查看 sp
library(sp)
p1 <- SpatialPoints(select(d1, long, lat))
p2 <- SpatialPoints(select(d2, long, lat))
spDists(p1, p2, longlat=TRUE, diagonal=TRUE)
# [1] 304.7427 267.2908 778.7028 3359.7988 (output is km)
由于您已经在使用 dplyr
,因此您可以轻松地将 sf
添加到您的工作流程中。在这里,我使用 long/lat 坐标和 long/lat 投影将您的数据框制作成具有 sf
列的数据框。然后,我将它们分别转换为以美国脚为基础的投影并计算距离。如果需要,您可以将该距离向量添加到两个初始数据帧的连接版本中。
要注意的一个注意事项是顺序——我按基本标签排列 d1_sf
和 d2_sf
,但如果这在更大或更复杂的数据集中效果不佳,或者有缺失的碱基,你可以在这里使用连接来检查。
library(tidyverse)
library(sf)
...
d1_sf <- st_as_sf(d1, coords = c("long", "lat"), crs = 4326) %>%
arrange(title)
d2_sf <- st_as_sf(d2, coords = c("long", "lat"), crs = 4326) %>%
arrange(Base)
distances <- st_distance(
st_transform(d1_sf, crs = 2234),
st_transform(d2_sf, crs = 2234),
by_element = T
)
distances
#> Units: US_survey_foot
#> [1] 1035387.8 916425.4 2591457.0 11553291.3
inner_join(d1, d2, by = c("title" = "Base"), suffix = c("1", "2")) %>%
mutate(dist = distances) %>%
mutate(dist_mi = dist / 5280)
#> # A tibble: 4 x 8
#> title lat1 long1 tas lat2 long2 dist dist_mi
#> <chr> <dbl> <dbl> <chr> <dbl> <dbl> <S3: units> <S3: units>
#> 1 base1 57.3 0.4 tas1 54.6 1.2 " 1035387.8 US_su… " 196.0962 US_su…
#> 2 base2 58.8 3.4 tas2 56.4 3.4 " 916425.4 US_su… " 173.5654 US_su…
#> 3 base3 47.2 3.5 tas3 54.2 3.5 " 2591457.0 US_su… " 490.8062 US_su…
#> 4 base4 57.8 1.2 tas4 54.6 56.6 11553291.3 US_sur… 2188.1234 US_sur…
由 reprex package (v0.2.0) 创建于 2018-08-13。