我有一个数据库,其中包含发生在美国特定地理位置的数万个事件。数据包括每个事件的 x、y 坐标,使用 NAD83 参考系统进行编码。我想编写或使用一种算法来可靠地获取与每个 NAD83 x,y 坐标关联的美国邮政编码。
我还没有使用 NAD83 参考系统的邮政编码定义。而且我以前从未做过这种编程。但是,找出给定的 x,y 坐标是否位于使用相同的 NAD83 参考系统定义的美国邮政编码的几何形状内似乎在直觉上很简单。
我对以下内容感兴趣:
我对指向指导性文章/教程、示例代码和 NAD83 邮政编码边界定义数据的任何链接感兴趣。我正在做网络搜索,但我想这个网站上的人可能会给我更多的专家指导。
如果您提供的代码不是用 Java 编写的,我可以采用其他语言编写的代码并将其改编为 Java 以达到我的目的。我的计算机上没有安装数据库软件,因为我只是使用 csv 或文本文件作为我的 Java 应用程序的输入。如果您有一些建议我使用的数据库,我将需要指向说明的链接,以了解如何将数据转换为可以导入编程语言(如 Java)的格式。
最后,我的数据集中的街道地址不包括邮政编码,街道地址是随意写的,因此很难清理地址数据以尝试从地址中获取邮政编码。我可以将数据隔离到几个相邻的城市,可能有几百个邮政编码,但我认为 NAD83 x,y 坐标是我推导出数据集中每个事件发生的邮政编码的最佳方法。我想通过邮政编码分析将我得到的邮政编码与我从美国人口普查等来源获得的关于每个邮政编码的其他数据链接起来
您可以在 java 中使用 GeoTools。这是一个在 shapefile 中搜索点的示例。
// projection/datum in SR-ORG:7169 (GCS NAD83)
File shapeFile = new File("zt08_d00.shp");
FileDataStore store = FileDataStoreFinder.getDataStore(shapeFile);
SimpleFeatureSource featureSource = store.getFeatureSource();
// Boulder, CO
Filter filter = CQL.toFilter("CONTAINS(the_geom, POINT(-105.292778 40.019444))");
SimpleFeatureCollection features = featureSource.getFeatures(filter);
for (SimpleFeature f : features) {
System.out.println(f.getAttribute('NAME'));
}
我从美国人口普查局收集的 2000 年人口普查的 5 位邮政编码制表区域 中抓取了一个 shapefile。我只为科罗拉多州使用了一个文件。您需要将它们合并成一个
FeatureSource
。运行此输出 80302 for Boulder, CO.
GeoTools 还允许您在需要时在投影之间转换。幸运的是,这些形状文件已经在 NAD83 中了。
我不知道从哪里得到邮政编码,但我想你可以谷歌一下,
the ZIP code of each state
。
对于问题 (2),首先您需要地理信息,即
the boundary of each state
。然后你只需枚举所有点(x,y)并确定它所在的多边形。
这是一个示例代码,它是为SGU124编写的。
#include <map>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 10005
using namespace std;
struct pnt{
int x,y;
};
struct seg{
pnt a,b;
} s[MAXN];
int n;
pnt p;
int h[MAXN<<1];
int k[MAXN<<1];
void work(){
int i,x,y,c = 0;
memset(h,0,sizeof(h));
memset(k,0,sizeof(k));
for (i=0;i<n;i++){
if (s[i].a.x<=p.x && p.x<=s[i].b.x && s[i].a.y<=p.y && p.y<=s[i].b.y){
printf("BORDER\n");
return;
}
if (s[i].a.x==s[i].b.x){
x = s[i].a.x;
y = p.y - p.x + x;
if (x<=p.x && s[i].a.y<=y && y<=s[i].b.y){
h[x+MAXN] = 1;
if (y==s[i].a.y) k[x+MAXN] |= 1;
else if (y==s[i].b.y) k[x+MAXN] |= 2;
}
}
else{
y = s[i].a.y;
x = p.x - p.y + y;
if (x<=p.x && s[i].a.x<=x && x<=s[i].b.x){
//printf("%d %d %d %d\n",s[i].a.x,s[i].a.y,s[i].b.x,s[i].b.y);
h[x+MAXN] = 1;
if (x==s[i].a.x) k[x+MAXN] |= 4;
else if (x==s[i].b.x) k[x+MAXN] |= 8;
}
}
}
for (i=p.x;i>=-10000;i--){
//if (h[i+MAXN]>0) printf("@ %d %d\n",i,k[i+MAXN]);
if (k[i+MAXN]!=9 && k[i+MAXN]!=6) c += h[i+MAXN];
}
//printf("p @ %d %d ",p.x,p.y);
if (c%2) printf("INSIDE\n");
else printf("OUTSIDE\n");
}
int main(){
freopen("sgu124.in","r",stdin);
int i;
while (~scanf("%d",&n)){
for (i=0;i<n;i++){
scanf("%d%d",&s[i].a.x,&s[i].a.y);
scanf("%d%d",&s[i].b.x,&s[i].b.y);
if (s[i].a.x>s[i].b.x || s[i].a.y>s[i].b.y) swap(s[i].a,s[i].b);
}
scanf("%d%d",&p.x,&p.y);
work();
//break;
}
return 0;
}
您提到您拥有可以使用的地址。在这种情况下,地址验证服务将允许您以编程方式根据地址和城市/州找到邮政编码。即使格式不正确,地址数据也可能使您达到目标的 90% 或 95%,剩下的留给清理和重新处理或尝试使用坐标来确定。
SmartyStreets 将使用您的数据上传一个 CSV 文件并执行地址验证(更正和标准化地址),然后使用 USPS 的数据验证地址。 SmartyStreets 的一项独特功能是他们不会对错误地址收取任何费用。这将允许您格式化和处理每个地址的各种排列(以尝试解释随意数据)并且仅在解决了肯定匹配时才付费。
为了全面披露,我是 SmartyStreets 的创始人。我们提供街道地址验证。