[英]R Find the Distance between Two US Zipcode columns
我想知道使用 R 計算兩個美國郵政編碼列之間的距離的最有效方法是什么。
我聽說過用於計算郵政編碼之間差異的 geosphere 包,但並不完全理解它,並且想知道是否還有其他方法。
例如說我有一個看起來像這樣的數據框。
ZIP_START ZIP_END
95051 98053
94534 94128
60193 60666
94591 73344
94128 94128
94015 73344
94553 94128
10994 7105
95008 94128
我想創建一個看起來像這樣的新數據框。
ZIP_START ZIP_END MILES_DIFFERENCE
95051 98053 x
94534 94128 x
60193 60666 x
94591 73344 x
94128 94128 x
94015 73344 x
94553 94128 x
10994 7105 x
95008 94128 x
其中 x 是兩個郵政編碼之間的英里差。
計算此距離的最佳方法是什么?
這是創建示例數據框的 R 代碼。
df <- data.frame("ZIP_START" = c(95051, 94534, 60193, 94591, 94128, 94015, 94553, 10994, 95008), "ZIP_END" = c(98053, 94128, 60666, 73344, 94128, 73344, 94128, 7105, 94128))
請讓我知道,如果你有任何問題。
任何建議表示贊賞。
感謝您的幫助。
有一個名為“zipcode”的方便的 R 包,它提供了一個包含郵政編碼、城市、州以及緯度和經度的表格。 所以一旦你有了這些信息,“geosphere”包就可以計算點之間的距離。
library(zipcode)
library(geosphere)
#dataframe need to be character arrays or the else the leading zeros will be dropped causing errors
df <- data.frame("ZIP_START" = c(95051, 94534, 60193, 94591, 94128, 94015, 94553, 10994, 95008),
"ZIP_END" = c(98053, 94128, 60666, 73344, 94128, 73344, 94128, "07105", 94128),
stringsAsFactors = FALSE)
data("zipcode")
df$distance_meters<-apply(df, 1, function(x){
startindex<-which(x[["ZIP_START"]]==zipcode$zip)
endindex<-which(x[["ZIP_END"]]==zipcode$zip)
distGeo(p1=c(zipcode[startindex, "longitude"], zipcode[startindex, "latitude"]), p2=c(zipcode[endindex, "longitude"], zipcode[endindex, "latitude"]))
})
關於輸入數據框的列類的警告。 郵政編碼應該是字符而不是數字,否則會丟棄前導零導致錯誤。
從 distGeo 返回的距離以米為單位,我將允許讀者確定正確的單位轉換為英里。
更新
郵政編碼包似乎已存檔。 有一個替換包:“zipcodeR”,它提供經度和緯度數據以及附加信息。
正如 Dave2e 提到的,原始 zipcode 包已經從 CRAN 中刪除,所以我們需要使用 zipcodeR 代替。
if (!require("zipcodeR"))install.packages("zipcodeR")
if (!require("geosphere"))install.packages("geosphere")
df <- data.frame(
"ZIP_START" = c(95051, 94534, 60193, 94591, 94128, 94015, 94553, 10994, 95008),
"ZIP_END" = c(98053, 94128, 60666, 73344, 94128, 73344, 94128, "07105", 94128),
stringsAsFactors = FALSE
)
data("zip_code_db")
df$distance_meters<-apply(df, 1, function(x){
startindex<-which(x[["ZIP_START"]]==zip_code_db$zipcode)
endindex<-which(x[["ZIP_END"]]==zip_code_db$zipcode)
distGeo(p1=c(zip_code_db[startindex, "lng"],
zip_code_db[startindex, "lat"]),
p2=c(zip_code_db[endindex, "lng"],
zip_code_db[endindex, "lat"]))
})
這是基於新 zipcodeR 包的修復。 歸功於 Dave2e。
OP 要求“最有效”,因此給出
geosphere
時,它的速度非常慢apply
本質上是一個循環函數,通常可以使用矢量化代碼擊敗我提出了一個使用data.table
和library(geodist)
的完全矢量化的解決方案
#dataframe need to be character arrays or the else the leading zeros will be dropped causing errors
df <- data.frame("ZIP_START" = c(95051, 94534, 60193, 94591, 94128, 94015, 94553, 10994, 95008),
"ZIP_END" = c(98053, 94128, 60666, 73344, 94128, 73344, 94128, "07105", 94128),
stringsAsFactors = FALSE)
library(zipcodeR)
library(data.table)
library(geodist)
## Convert the zip codes to data.table so we can join on them
## I'm using the centroid of the zipcodes (lng and lat).
## If you want the distance to the endge of the zipcode boundary you'll
## need to convert this into a spatial data set
dt_zips <- as.data.table( zip_code_db[, c("zipcode", "lng", "lat")])
## convert the input data.frame into a data.talbe
setDT( df )
## the postcodes need to be characters
df[
, `:=`(
ZIP_START = as.character( ZIP_START )
, ZIP_END = as.character( ZIP_END )
)
]
## Attach origin lon & lat using a join
df[
dt_zips
, on = .(ZIP_START = zipcode)
, `:=`(
lng_start = lng
, lat_start = lat
)
]
## Attach destination lon & lat using a join
df[
dt_zips
, on = .(ZIP_END = zipcode)
, `:=`(
lng_end = lng
, lat_end = lat
)
]
## calculate the distance
df[
, distance_metres := geodist::geodist_vec(
x1 = lng_start
, y1 = lat_start
, x2 = lng_end
, y2 = lat_end
, paired = TRUE
, measure = "haversine"
)
]
## et voila - note the missing zipcode 6066 and 73344
df
# ZIP_START ZIP_END lng_start lat_start lng_end lat_end distance_metres
# 1: 95051 98053 -121.98 37.35 -122.02 47.66 1147708.60
# 2: 94534 94128 -122.10 38.20 -122.38 37.62 69090.01
# 3: 60193 60666 -88.09 42.01 NA NA NA
# 4: 94591 73344 -122.20 38.12 NA NA NA
# 5: 94128 94128 -122.38 37.62 -122.38 37.62 0.00
# 6: 94015 73344 -122.48 37.68 NA NA NA
# 7: 94553 94128 -122.10 38.00 -122.38 37.62 48947.02
# 8: 10994 07105 -73.97 41.10 -74.15 40.72 44930.17
# 9: 95008 94128 -121.94 37.28 -122.38 37.62 54263.61
另請注意,返回的距離以米為單位。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.