如何获取美国邮政编码的边界坐标?

19

有没有一项服务/API可以获取邮政/邮编并返回边界(周长)坐标,以便我可以在MS SQL数据库中构建几何对象?

通过边界坐标,我指的是想要检索构成美国邮政编码定义多边形的GPS坐标列表。


你需要一个API来获取美国或国家的邮政编码边界吗? - Eric Leschinski
状态无关紧要 - 我正在寻找定义给定邮政编码的坐标序列,以便我可以构造一个多边形。 - ecco88
1
好的...所以将线条替换为多边形。我希望每个人都能理解我想要实现的目标。 - ecco88
2
不方便的是,邮政编码在技术上并不是多边形,它们只是线条...我们绘制的多边形实际上是人工表示,往往存在缺陷。我与一家获得USPS授权以验证地址并进行地理编码的公司合作。我们不做您要求的事情的原因之一是有时会产生误导。 - Matt
1
我刚刚又仔细了解了一下,我一直以为邮政编码代表着地区,但实际上并不是这样。感谢您指引我正确的方向。如果您将此作为答案发布,我想将其标记为已解决。 - ecco88
6个回答

58
我的评论是关于ZIP码不是多边形的阐述...
我们通常认为ZIP码是区域(多边形),因为我们说:“哦,我住在这个ZIP码中...”,这给人以包含区域的印象,也许ZIP代表“区域改进计划”的事实有助于与多边形的错误关联。
实际上,ZIP码是表示邮递员路线的线。几何上,线没有面积。就像线是沿着坐标平面的一系列点的字符串一样,ZIP码线是在USPS指定地址的抽象空间中表示递送点的字符串。 它们与地理坐标无关。但你会发现,它们似乎是地理定位的,因为对于邮递员来说,完全不考虑距离和位置是低效的。
什么是“USPS指定地址的抽象空间”?这就是我描述的由美国邮政服务维护的可递送位置的大型神秘数据库。地址不是根据地理位置分配的,而是根据邮递员行驶的路线分配的,通常与街道和可行性相关。
一些五位数字的邮政编码只代表一个建筑物、建筑群,甚至是一个建筑物的单层(是的,多个邮政编码可以在同一坐标上,因为它们的投递点是垂直分层的)。其中一些——包括其他的——是“独特”的邮政编码。公司和大学经常为营销或组织目的获得自己的邮政编码。例如,邮政编码“12345”属于通用电气 在纽约州的斯克内克塔迪市。(编辑:在 Google 地图的先前版本中,当您跟随该链接时,您会注意到放置标记正在悬停,因为它指向一个邮政编码,这不是一个坐标。虽然大多数美国邮政编码以前都在 Google 地图上显示一个区域,但这些类型不能因为 USPS 并没有“拥有”它们,所以说,它们没有面积。)

仅供娱乐,让我们尝试验证一个独特邮政编码中的地址。前往SmartyStreets,输入12345中的虚假地址,例如:

街道地址:999 Sdf sdf

邮政编码:12345

当您尝试验证它时,请注意...它是有效的!为什么?美国邮政服务(USPS)将把一件物品递送到该独特邮政编码的接收器中,但此时,就由GE来分发了。在邮政编码内部的任何内容对USPS都不重要,包括街道地址(技术上称为“交付线1”)。许多大学也以类似的方式运作。这里有更多相关信息。

现在,尝试相同的虚假地址,但不使用邮政编码,而是使用城市/州:

街道地址:999 Sdf sdf

城市:Schenectady

州:NY

它无法验证。这是因为尽管Schenectady包含12345,地址是“有效的”,但它在几何上与Schenectady的“真实”邮政编码相交。
再看另一个例子:军事。某些海军舰艇有自己的邮政编码。军事地址是完全不同的地址类别,但使用相同的名称空间。船只移动。地理坐标不会移动。
ZIP精度是另一个有趣的问题。 5位数字的ZIP代码是最不“精确”的(虽然术语“具体”在这里可能更有意义,因为ZIP代码并不能确定任何东西)。 7位和9位数字的ZIP代码是最具体的,通常在城市地区下到街区或社区级别。但由于每个ZIP代码的大小都不同,因此很难确定您所说的实际距离。
9位数字的ZIP代码可能被分配到建筑物的一层,因此您可能有数百个地址的重叠ZIP代码。
底线:与普遍观念相反,ZIP代码不提供地理或边界数据。它们变化很大,除非您正在投递邮件或包裹,否则它们实际上并不那么有用...但USPS的工作是设计高效的邮递员路线,而不是将人口划分为坐标区域。
这更像是人口普查局的工作。由于ZIP码很“方便”使用,他们已经编制了地图边界列表。为此,他们将一堆地址分成了人口普查区块。然后,他们汇总了USPS ZIP码数据,以找到其人口普查区块(其中包含一些粗略的坐标数据)与ZIP码之间的关系。因此,我们有了近似值,可以将一条线绘制成多边形。(显然,他们通过根据内容调整2D多边形来适应线性数据,将1D线转换为2D多边形 - 对于每个非唯一的常规ZIP码。)
从他们的网站上(上面的链接):
一个邮政编码制表区(ZCTA)是一个统计地理实体,近似于美国邮政服务五位数字或三位数字邮政编码的投递区域。ZCTA是与美国人口普查局的主地址文件(MAF)中的地址相关联的具有相同主要邮政编码的普查区块的聚合物。三位数的ZCTA代码适用于美国人口普查局在其MAF中没有五位数字邮政编码信息的大连续区域。ZCTA不精确地描绘邮政编码投递区域,并且不包括用于邮件投递的所有邮政编码。美国人口普查局已将ZCTA确定为类似于但取代1990年及以前人口普查中与邮政编码一起进行的数据制表的新地理实体。

美国人口普查局的数据集不完整,有时也不准确。Google的数据仍然存在漏洞(12345是一个比较好的例子),但是Google最终将通过手动检查每个地址和邮政编码来解决这个问题。他们已经在做这件事,但还没有使他们的地图数据完美。自然地,访问此数据受到API条款的限制,并且提高这些费用非常昂贵。

哎呀,我累坏了。希望这能澄清事情。免责声明:我曾经是SmartyStreets的开发人员。有关使用地址数据进行地理编码的更多信息。

有关邮政编码的更多信息


看起来美国人口普查局已经更改了获取地图边界的位置。现在可以在此处获得:https://www.census.gov/geo/maps-data/data/cbf/cbf_zcta.html - lsowen
@Matt,有没有任何API可以根据邮政编码返回建筑物的名称。我想只允许住在公寓楼里的用户在我的应用程序中注册。 - bibscy
如果企业名称已在USPS注册,则CASS认证的API将具有该信息;不确定建筑物名称是否也包含在内。如果您只想知道地址是否有辅助单元(如公寓、信箱或套房),则API也应该具有该信息。我曾经工作过的公司就有这样一种带有该信息的API。 - Matt
目前有“太多待处理的编辑”,但美国人口普查局邮政编码分区页面已经再次移动 - Dan Villarreal
目前有太多待处理的编辑,但美国人口普查局的邮政编码分区页面又被移动了。请参考此链接 - Dan Villarreal

1
您所要求的是提供“免费邮政编码地理编码”服务。市面上有一些提供此类服务的网站,但质量参差不齐。如果您自己编写此类代码,可能会遇到以下几个问题:
1. 邮政编码可以分配给单个建筑物或邮局。 2. 邮政编码被视为多边形区域。将邮政编码投影到多边形区域需要您猜测一个邮政编码和另一个之间的边界在哪里。 3. 邮政编码地址数据仅指定邮政编码的中心位置。邮政编码数据提供地址的大致位置。存在于一个邮政编码和另一个邮政编码之间的邮寄地址可能存在争议,因为无法确定它实际上属于哪个邮政编码。 4. 一个邮寄地址可能离11111邮政编码更近,但其官方邮政编码却是更远的11112邮政编码点。 Google Maps有一个地理编码API: Google Maps API是客户端JavaScript。您可以通过HTTP请求直接从PHP查询地理编码系统。然而,Google Maps只能提供美国邮政服务提供给他们的信息,即代表邮政编码中心的点。

https://developers.google.com/maps/#Geocoding_Examples

使用谷歌地图绘制城市/邮政编码多边形

关于将邮政编码投影到其纬度/经度边界框的想法

美国大约有43,000个邮政编码。这个数字会随着每月所做更改的数量而波动。 USPS使用的邮政编码不表示为多边形,也没有硬性和快速的边界。

USPS(美国邮政服务)是定义每个邮政编码纬度/经度的机构。任何将邮政编码解析为地理位置的软件都需要每周更新。一家名为Alignstar的公司提供邮政编码的人口统计和GIS数据(http://www.alignstar.com/data.html)。

给定一个实际(邮寄)地址,找到地理坐标以便在地图上显示该位置。

如果您想可靠地预测邮政编码的形状,您需要使用暴力方法并询问:“按邮政编码给我每个街道地址”,然后在这些不规则的区域周围绘制框。然后,您可以大致了解邮政编码覆盖的地理区域。

http://vterrain.org/Culture/geocoding.html

如果您将数百万个邮寄地址点投入算法中,将每个点解析为纬度/经度,您可能能够构建该邮政编码的基本边界框。您需要重新运行此算法,并且理论上它会在邮政编码数字移动时自我修复。

其他想法

http://shop.delorme.com/OA_HTML/DELibeCCtpSctDspRte.jsp?section=10075

http://www.zip-codes.com/zip-code-map-boundary-data.asp


谢谢您的建议,但我并不想自己构建这个服务。我认为美国邮政服务(或第三方)可能会提供一种方法来跟踪邮政编码边界。我找不到它,希望有人在此之前研究过这个问题。 - ecco88

0

我认为这是你需要的,它使用美国人口普查作为存储库:US Zipcode

边界 API: https://www.boundaries-io.com

上述 API 按邮政编码、城市和州显示美国边界(GeoJson)。你应该以编程方式使用 API 来处理大量结果。

enter image description here

声明:我在这里工作


是的,传递无效的查询参数会导致错误......这应该是可以预料的。人口普查边界文件的链接在说明中。@Enkode。发送电子邮件给支持部门将帮助您解决任何问题。新年快乐! - Jeryl Cook

0

步骤1:下载cb_2018_us_zcta510_500k.zip文件

https://www.census.gov/geographies/mapping-files/time-series/geo/carto-boundary-file.html

如果您想将它们保存在mysql中

步骤2:在您的mysql中创建一个名为“spatialdata”的数据库,运行以下命令 ogr2ogr -f "MySQL" MYSQL:"spatialdata,host=localhost,user=root" -nln "map" -a_srs "EPSG:4683" cb_2018_us_zcta510_500k.shp -overwrite -addfields -fieldTypeToString All -lco ENGINE=MyISAM

我已经将文件上传到github(https://github.com/sahilkashyap64/USA-zipcode-boundary/blob/master/USAspatialdata.zip

在您的“spatialdata db”中,将有两个名为map和geometry_columns的表。

  1. 在'map'中将有一个名为“shape”的列。

形状列的类型为“几何”,其中包含多边形/多边形文件

  1. 在'geometry_columns'中将定义srid

如何检查点是否落在多边形内

SELECT * FROM map WHERE ST_Contains( map.SHAPE, ST_GeomFromText( 'POINT(63.39550 -148.89730 )', 4683 ) )

想要在地图上显示边界

选择zcta5ce10作为zipcode,从map中选择ST_Contains(map.SHAPE, ST_GeomFromText('POINT(34.1116 -85.6092)', 4683))的ST_AsGeoJSON(SHAPE) sh。

"ST_AsGeoJSON"将空间数据返回为geojson格式。 使用 http://geojson.tools/ "HERE maps" 检查geojson的形状。

如果您想生成topojson

mapshaper可以将shapefile转换为topojson(无需将其转换为kml文件) npx -p mapshaper mapshaper-xl cb_2018_us_zcta510_500k.shp snap -simplify 0.1% -filter-fields ZCTA5CE10 -rename-fields zip=ZCTA5CE10 -o format=topojson cb_2018_us_zcta510_500k.json

如果您想将shapefile转换为kml

`ogr2ogr -f KML tl_2019_us_zcta510.kml -mapFieldType Integer64=Real tl_2019_us_zcta510.shp

我使用mapbox gl来显示两个邮政编码区域

  1. 示例:https://sahilkashyap64.github.io/USA-zipcode-boundary/
  2. 代码:https://github.com/sahilkashyap64/USA-zipcode-boundary

0

SQL Server解决方案

  1. 从美国人口普查中下载形状文件: https://catalog.data.gov/dataset/2019-cartographic-boundary-shapefile-2010-zip-code-tabulation-areas-for-united-states-1-500000
  2. 然后我发现了这个存储库,可以将形状文件导入到SQL Server中,速度非常快,无需额外编码:https://github.com/xfischer/Shape2SqlServer
  3. 然后我可以编写自己的脚本来查找在我创建的多边形内的邮政编码:

DECLARE @polygon GEOMETRY;
DECLARE @isValid bit = 0;
DECLARE @p nvarchar(2048) = 'POLYGON((-120.1547 39.2472,-120.3758 39.1950,-120.2124 38.7734,-119.6590 38.8162,-119.6342 39.3672,-120.1836 39.2525,-120.1547 39.2472))'
SET @polygon = GEOMETRY::STPolyFromText(@p,4326)

SET @isValid = @polygon.STIsValid()
IF (@isValid = 1)
    SET @polygon = @polygon.MakeValid();

SET @isValid = @polygon.STIsValid()
IF (@isValid = 1)
BEGIN

    SELECT * FROM cb_2019_us_zcta510_500k
        WHERE geom.STIntersects(@polygon) = 1

END
ELSE
    SELECT 'Polygon not valid'
 


-2

我认为世界GeoJson链接和谷歌地图Geocode API可以帮助你。 例如:您可以使用Geocode API对邮政编码进行编码,您将获得城市、州、国家,然后,您可以从世界和美国GeoJson中获取边界,我有一个美国州边界的示例,如dsdlink


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接