在ESRI shape文件中将GIS点与多边形匹配

4
我有一个ESRI形状文件,其中包含大约150个连续的地理区域(多边形),它们共同组成一个地理区域。 我还有一个包含60,000个事件的csv文件,每个事件都具有唯一的x,y点坐标集。 csv文件中的每个事件都发生在形状文件中的一个(仅一个)多边形内,但我不知道要将哪个多边形与每个记录相关联。 因此,我需要编写一个算法,以查找60,000个事件发生的多边形的身份。 我需要编写的算法的输出将使我随后能够计算统计数据,例如特定类型的事件在特定多边形(地理区域)中发生的可能性。
(当然,形状文件不仅是一个文件。 它是一个目录,其中包含8个文件,文件扩展名包括.dbf,.prj,.qix,.sbn,.sbx,.shp,.xml和.shx。)
我没有ArcGIS许可证。 我在http://resources.arcgis.com/content/geodatabases/10.0/file-gdb-api找到了File Geodatabase API,但我不确定它是否是正确的工具集,而且我也很难找到示例代码。
有人可以向我展示一些代码,以查找大量点(来自外部数据源,如csv文件)中的每个点所在的多边形(来自形状文件)吗?
此外,我需要指定我需要能够为每个事件向csv记录添加相关多边形的特定代码。 因此,仅仅将点绘制在地图上以可视化哪些多边形包含事件是不够的。 我根本不需要可视化这些数据。 相反,我需要能够为csv文件中的每个事件记录标记一个多边形ID,以便我可以进行非可视化性质的后续数值分析。
也感谢有关此主题的文章,教程和其他资源的链接。 我想象人们每天都解决这个问题,因此如果人知道如何寻找它,就必须有一个已建立的代码库。 我每天都用Java编码,因此首选Java解决方案。 但是,如果您有用其他语言编写的好的代码示例,则我可以将其移植到其他语言中。
编辑:
我尝试了以下基于Spacedman建议的R代码,并收到以下错误消息:
> myCSV <- read.csv(file="myCSVFile.csv",head=TRUE,sep=",")  
> pts = SpatialPoints(myCSV)  
> ZipCodes = readShapeSpatial("path/myshapefile.shp")  
> overlay(myCSV,ZipCodes)  
Error in function (classes, fdef, mtable)  : unable to find an inherited method for function "overlay", for signature "data.frame", "SpatialPolygonsDataFrame"  
> 

请参见下面的其他评论。

第二次编辑:
我最终使用的 R 代码是:

myCSV <- read.csv(file="myData.csv",head=TRUE,sep=",")  
pts = SpatialPoints(myCSV)  
ZipCodes = readShapeSpatial("myPath/ZipCodes.shp")  
write.csv(ZipCodes$ZIPCODE[overlay(pts,ZipCodes)], "ZipMatches.csv", quote=FALSE, row.names=FALSE)

注意:我必须使用:
summary(ZipCodes)  

找到包含邮政编码的编码字段名称。在运行summary(ZipCodes)之前,脚本只输出每个邮政编码的索引而不是邮政编码本身。


2
我认为用R编码并不太难。R是一个可接受的解决方案吗? - Roman Luštrik
@RomanLuštrik,R可以工作。我很想看到示例代码。+1为了帮助我而尝试。 - CodeMed
你正在将myCSV覆盖在ZipCodes上,而不是'pts' SpatialPoints对象上!错误信息显示“我不知道如何将数据框叠加到空间多边形数据框上”。overlay(pts,ZipCodes)应该可以工作。 - Spacedman
@Spacedman,非常感谢。我已经上面发布了我最终使用的代码。但我有一个问题。该代码的输出是与我的输入csv文件具有相同长度的csv文件,并且在输入中x,y坐标为零的每个记录处包含NA。因此,我认为只需手动将输出插入到原始缺少此数据的电子表格作为新列即可。您认为我应该做些什么以验证每个输出代码与原始数据中的每一行的对应关系吗?如果需要,我还能做些什么?我只是假设输出和输入是按照相同的顺序排列的。 - CodeMed
是的,覆盖层的输出顺序与您的输入中的“pts”相同,这与您的myData.csv的顺序相同。 - Spacedman
2个回答

9

JTS是执行点/多边形操作的Java库:

http://www.vividsolutions.com/jts/JTSHome.htm

您可能需要使用其他工具来读取shapefile文件,比如:

http://openmap.bbn.com/doc/api/com/bbn/openmap/layer/shape/ShapeFile.html

或者使用OGR和GDAL的Java绑定:

http://gdal.org/java/

然而,您可能只需要开源GIS软件包:Quantum GIS是我最喜欢的,但如果您想要一个基于Java的软件包,有几个选项 - OpenJump、gvSIG(www.osgeo.org提供所有相关内容)。

在R中,如果您已将点坐标读入矩阵或数据框中:

> xy
            [,1]       [,2]
 [1,]  15.224275  -0.840066
 [2,]  -1.207046   7.959644
 [3,]   9.397658  17.426323
 [4,]  28.242840 -29.581008
 [5,]  18.664603  15.361146
 [6,]   0.975846   8.534910
 [7,] -10.941825  10.438541
 [8,] -10.331097  20.260005
 [9,]   8.105570   9.595169
[10,] -14.468177  14.366980

然后,使用maptools软件包及其依赖项:
> require(maptools)

首先,从您的坐标创建一个SpatialPoints对象:

> pts = SpatialPoints(xy)

然后读取您的shapefile文件:

> africa=readShapeSpatial("/path/to/africa.shp")

现在开始叠加:

> overlay(pts,africa)
 [1] 12 20 39 27 10 55 22 33 40 45

这是shapefile中的行号向量。您可以轻松地在shapefile中查找属性:

> africa$CNTRY_NAME[overlay(pts,africa)]
 [1] Congo      Ghana      Niger      Lesotho    Chad       Togo      
 [7] Guinea     Mauritania Nigeria    Senegal   
61 Levels: Algeria Angola Benin Botswana Burkina Faso Burundi ... Zimbabwe

如果您想将向量写入CSV文件,

> write.csv(africa$CNTRY_NAME[overlay(pts,africa)],file="out.csv")

生成:

"","x"
"1","Congo"
"2","Ghana"
"3","Niger"
"4","Lesotho"
"5","Chad"
"6","Togo"
"7","Guinea"
"8","Mauritania"
"9","Nigeria"
"10","Senegal"

逗号分隔,带有名为'x'的标题,并用引号括起来。使用其他选项来编写.csv文件时,这些内容是可调整的。

如果您的某些点落在多边形外部,则返回的叠加向量将是一个“NA”值,您可能需要测试此值:

> if(any(is.na(overlay(pts,africa)))){stop("splash!")}
Error: splash!

Nuff?


谢谢。+1 帮我找到了解决方法。我以前编写过 R 代码。如果您认为这样做能让编码变得容易,我可以再次下载并学习它。我知道如何将 .csv 数据导入 R 中,并且我可能可以轻松地使您的“匹配”输出到 .csv 中。但是您是否愿意发布更完整的版本,以便实现我在上面的原始帖子中概述的整个任务所需的 R 脚本呢?谢谢。 - CodeMed
谢谢。我目前正在下载并打算尝试这些方法。谢谢帮忙,点赞! - CodeMed
我下载了R和maptools。我导入了我的csv数据。但是我的csv数据文件有几个字段,其中x和y只是两个字段。即使我剥离所有多余的字段,我可能仍然需要至少保留recordID字段以及x和y字段。但在我开始编写一堆复杂的字符串拆分代码之前,是否有一种最简单的方法可以处理每个包含10列的60,000行csv文件,当SpatialPoints()似乎只想要两列xy时?我想使用最有效的代码。 - CodeMed
我正在研究您使用的命令,但是我无法找到任何关于spatialpoints()和overlay()的文档。我已经在Google上搜索了这些术语,并在各种PDF R手册中进行了关键字搜索。由于我的CSV数据有额外的字段(请参见其他问题),因此我还无法运行这些命令,但我至少尝试理解其语法。您是否知道网上有关该语法的任何好的解释?再次感谢。 - CodeMed
1
SpatialPoints和overlay来自“sp”包,如果您安装了maptools包,则可能已经获得了它。如果您可以执行library(maptools)和library(sp),那么您可能可以执行help(SpatialPoints)-大小写很重要。对于您的CSV,您可以使用read.table或read.csv将其全部读入数据框,然后仅提取x和y列。任何R入门都会告诉您如何做到这一点。例如,在此处的第6和第7节http://cran.r-project.org/doc/manuals/R-intro.html,或在此处提出新问题。但首先搜索! - Spacedman
谢谢你再次提供帮助。我下次登录时会查看这个问题。现在我需要参加一个会议。目前,我在我的原始帖子末尾发布了一些代码,它识别了当我尝试运行你建议的代码时遇到的错误消息。它似乎不喜欢overlay()函数。 - CodeMed

8

如果您不想编程,也可以考虑使用QGIS软件来实现GUI解决方案。

它可以轻松加载您的多边形 shape 文件,并且还可以处理从 CSV 文件创建点图层

enter image description here

这里不应该有60k个点的问题-我已经在我的笔记本电脑上处理过更大的数据集。

获取多边形的属性就像在两个数据集上执行空间连接一样容易。

enter image description here

enter image description here

此操作的结果将是等效于输入数据加入多边形属性的点层。

如果涉及太多点击,或者需要频繁重复此类分析,则可以考虑使用PyQGIS脚本化此过程。

有关其他解决方案,请查看 GIS SE 网站上的Fastest way to spatially join a point CSV with a polygon Shapefile 问题。


1
谢谢。我今天会下载并尝试这个。+1努力帮忙。 - CodeMed

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