从 R 中的两个数据表中找到最接近的邮政编码
Find closest Zip Code to another from two data tables in R
我有两个单独的数据 table,我想找到从一个数据 table 到另一个的壁橱邮政编码。从 SiteZip table,我希望邮政编码通过 ConsumerZip table 循环以获得邮政编码之间的最短距离。我使用 zipcodeR 包为其分配纬度和经度。下面是两个 table。第一个 table 是商店的位置。其他 table 是客户所在地。我希望能够创建一个 table 来显示每个客户最近的商店。我已经研究了几天,但没有找到很多符合我正在寻找的请求。最终,我会根据客户位置用密度圆绘制商店位置。预先感谢您提供的任何帮助。
head(StoreZip)
Zip Store Address1 City State lat lng
1: 01026 11111 151 South Street Cummington MA 42.48 -72.93
2: 01040 11112 303 Beech St. Holyoke MA 42.22 -72.64
3: 01104 11113 417 Liberty St. Springfield MA 42.13 -72.57
4: 01104 11114 2155 Main St. Springfield MA 42.13 -72.57
5: 01301 11115 55 Federal St. Greenfield MA 42.63 -72.59
6: 01301 11116 1 Arch Place Greenfield MA 42.63 -72.59```
```head(CustomersZip)
Zip ID Address1 City State lat lng
1: 01001 65484654805 1548 MAIN STREET AGAWAM MA 42.07 -72.63
2: 01001 64846124846 569 MAPLE ST AGAWAM MA 42.07 -72.63
3: 01001 68421548945 68 PLANTATION DR AGAWAM MA 42.07 -72.63
4: 01001 84051545484 154 South DR AGAWAM MA 42.07 -72.63
5: 01001 97545154848 985 Main St AGAWAM MA 42.07 -72.63
6: 01002 64841515484 54 KING ST PELHAM MA 42.38 -72.52
这是将每个 CustomersZip$ID
映射到最接近的 StoreZip$Store
的解决方案:
library(data.table)
# library(geosphere) # distHaversine
CustomersZip[
, Store := StoreZip$Store[
which.min(geosphere::distHaversine(
cbind(first(lng), first(lat)),
StoreZip[, cbind("lng", "lat"), with = FALSE])) ]
, by = ID ]
CustomersZip
# Zip ID lat lng Store
# <int> <char> <num> <num> <int>
# 1: 1001 65484654805 42.07 -72.63 11113
# 2: 1001 64846124846 42.07 -72.63 11113
# 3: 1001 68421548945 42.07 -72.63 11113
# 4: 1001 84051545484 42.07 -72.63 11113
# 5: 1001 97545154848 42.07 -72.63 11113
# 6: 1002 64841515484 42.38 -72.52 11112
演练:
distHaversine
对两个参数进行操作,通常是矩阵(或帧),每个参数有两列;它如何计算距离取决于每个参数 p1
和 p2
中的点数:
- 如果
p1
有一个点,则计算所有p2
点到个别p1
点;同样,如果 p2
有一个点;
- 如果
p1
和p2
的点数相同,则逐点计算距离,即row1与row1,row2与row2等;它不对“row1 with row1,row2,row3,...”、“row2 with row1,row2,row3,...”进行笛卡尔展开,因此必须外部发生
- 因此,我们一次处理一个客户,找到距离最小 (
which.min
) 的商店并存储其 Store
id
- 虽然这个示例数据不是一个因素,但我选择按
CustomersZip$ID
对其进行分组,并仅使用为该客户找到的 first
lat/lng;如果客户可能有不同的积分,则删除 first
调用,并改为使用 by = seq_len(nrow(CustomersZip))
分组;如果不需要这一步,它仍然会计算出相同的结果,唯一的损失是多次计算相同距离的效率
可重复使用的数据(问题中的一部分):
StoreZip <- fread("
Zip Store lat lng
01026 11111 42.48 -72.93
01040 11112 42.22 -72.64
01104 11113 42.13 -72.57
01104 11114 42.13 -72.57
01301 11115 42.63 -72.59
01301 11116 42.63 -72.59")
CustomersZip <- fread("
Zip ID lat lng
01001 65484654805 42.07 -72.63
01001 64846124846 42.07 -72.63
01001 68421548945 42.07 -72.63
01001 84051545484 42.07 -72.63
01001 97545154848 42.07 -72.63
01002 64841515484 42.38 -72.52", colClasses = list(character="ID"))
我有两个单独的数据 table,我想找到从一个数据 table 到另一个的壁橱邮政编码。从 SiteZip table,我希望邮政编码通过 ConsumerZip table 循环以获得邮政编码之间的最短距离。我使用 zipcodeR 包为其分配纬度和经度。下面是两个 table。第一个 table 是商店的位置。其他 table 是客户所在地。我希望能够创建一个 table 来显示每个客户最近的商店。我已经研究了几天,但没有找到很多符合我正在寻找的请求。最终,我会根据客户位置用密度圆绘制商店位置。预先感谢您提供的任何帮助。
head(StoreZip)
Zip Store Address1 City State lat lng
1: 01026 11111 151 South Street Cummington MA 42.48 -72.93
2: 01040 11112 303 Beech St. Holyoke MA 42.22 -72.64
3: 01104 11113 417 Liberty St. Springfield MA 42.13 -72.57
4: 01104 11114 2155 Main St. Springfield MA 42.13 -72.57
5: 01301 11115 55 Federal St. Greenfield MA 42.63 -72.59
6: 01301 11116 1 Arch Place Greenfield MA 42.63 -72.59```
```head(CustomersZip)
Zip ID Address1 City State lat lng
1: 01001 65484654805 1548 MAIN STREET AGAWAM MA 42.07 -72.63
2: 01001 64846124846 569 MAPLE ST AGAWAM MA 42.07 -72.63
3: 01001 68421548945 68 PLANTATION DR AGAWAM MA 42.07 -72.63
4: 01001 84051545484 154 South DR AGAWAM MA 42.07 -72.63
5: 01001 97545154848 985 Main St AGAWAM MA 42.07 -72.63
6: 01002 64841515484 54 KING ST PELHAM MA 42.38 -72.52
这是将每个 CustomersZip$ID
映射到最接近的 StoreZip$Store
的解决方案:
library(data.table)
# library(geosphere) # distHaversine
CustomersZip[
, Store := StoreZip$Store[
which.min(geosphere::distHaversine(
cbind(first(lng), first(lat)),
StoreZip[, cbind("lng", "lat"), with = FALSE])) ]
, by = ID ]
CustomersZip
# Zip ID lat lng Store
# <int> <char> <num> <num> <int>
# 1: 1001 65484654805 42.07 -72.63 11113
# 2: 1001 64846124846 42.07 -72.63 11113
# 3: 1001 68421548945 42.07 -72.63 11113
# 4: 1001 84051545484 42.07 -72.63 11113
# 5: 1001 97545154848 42.07 -72.63 11113
# 6: 1002 64841515484 42.38 -72.52 11112
演练:
distHaversine
对两个参数进行操作,通常是矩阵(或帧),每个参数有两列;它如何计算距离取决于每个参数p1
和p2
中的点数:- 如果
p1
有一个点,则计算所有p2
点到个别p1
点;同样,如果p2
有一个点; - 如果
p1
和p2
的点数相同,则逐点计算距离,即row1与row1,row2与row2等;它不对“row1 with row1,row2,row3,...”、“row2 with row1,row2,row3,...”进行笛卡尔展开,因此必须外部发生
- 如果
- 因此,我们一次处理一个客户,找到距离最小 (
which.min
) 的商店并存储其Store
id - 虽然这个示例数据不是一个因素,但我选择按
CustomersZip$ID
对其进行分组,并仅使用为该客户找到的first
lat/lng;如果客户可能有不同的积分,则删除first
调用,并改为使用by = seq_len(nrow(CustomersZip))
分组;如果不需要这一步,它仍然会计算出相同的结果,唯一的损失是多次计算相同距离的效率
可重复使用的数据(问题中的一部分):
StoreZip <- fread("
Zip Store lat lng
01026 11111 42.48 -72.93
01040 11112 42.22 -72.64
01104 11113 42.13 -72.57
01104 11114 42.13 -72.57
01301 11115 42.63 -72.59
01301 11116 42.63 -72.59")
CustomersZip <- fread("
Zip ID lat lng
01001 65484654805 42.07 -72.63
01001 64846124846 42.07 -72.63
01001 68421548945 42.07 -72.63
01001 84051545484 42.07 -72.63
01001 97545154848 42.07 -72.63
01002 64841515484 42.38 -72.52", colClasses = list(character="ID"))