是否可以使用没有ArcMap许可证的Python查看Shapefile的内容?


40

我想知道是否可以在没有获得ArcMap许可的情况下使用Python查看shapefile的内容。这种情况是,您不仅可以通过ESRI软件,还可以通过许多不同的应用程序创建shapefile。我想创建一个Python脚本,该脚本检查空间参考,要素类型,属性名称和定义以及shapefile中字段的内容,并将它们与一组可接受的值进行比较。即使组织没有任何ESRI许可证,我也希望此脚本能够运行。为此,您是否必须使用ArcPy或不使用ArcPy就能挖入shapefile?


1
这取决于您要付出多少努力。.有几个开源库会有所帮助(根据Aarons的回答,我喜欢OGR),但是如果您真的想控制(并准备为此工作),Shapefile (最初由Esri提供)是一种开放格式,请参见en.wikipedia.org/wiki/Shapefile
Michael Stimson,

1
最近(过去几年)的ESRI shapefile隐藏在其新的地理数据库格式中。除ARCxxx软件外,似乎没有其他方法可以破坏它们。许多公共机构正在将其用于公共信息……可耻。

Answers:


34

我建议您熟悉Python GDAL / OGR API以同时使用矢量和栅格数据。开始使用GDAL / OGR的最简单方法是通过python发行版,例如python(x,y)AnacondaOSGeo4W

有关将GDAL用于特定任务的更多详细信息:

另外,我会推荐USU的以下教程来帮助您入门。


借鉴以上示例,以下脚本使用FOSS工具执行以下操作:

  1. 检查空间参考
  2. 获取shapefile字段和类型
  3. 检查用户定义字段中的行是否包含某些值

# Import the necessary modules
from  osgeo import ogr, osr

driver = ogr.GetDriverByName('ESRI Shapefile')
shp = driver.Open(r'C:\your\shapefile.shp')

# Get Projection from layer
layer = shp.GetLayer()
spatialRef = layer.GetSpatialRef()
print spatialRef

# Get Shapefile Fields and Types
layerDefinition = layer.GetLayerDefn()

print "Name  -  Type  Width  Precision"
for i in range(layerDefinition.GetFieldCount()):
    fieldName =  layerDefinition.GetFieldDefn(i).GetName()
    fieldTypeCode = layerDefinition.GetFieldDefn(i).GetType()
    fieldType = layerDefinition.GetFieldDefn(i).GetFieldTypeName(fieldTypeCode)
    fieldWidth = layerDefinition.GetFieldDefn(i).GetWidth()
    GetPrecision = layerDefinition.GetFieldDefn(i).GetPrecision()
    print fieldName + " - " + fieldType+ " " + str(fieldWidth) + " " + str(GetPrecision)

# Check if rows in attribute table meet some condition
inFeature = layer.GetNextFeature()
while inFeature:

    # get the cover attribute for the input feature
    cover = inFeature.GetField('cover')

    # check to see if cover == grass
    if cover == 'trees':
        print "Do some action..."

    # destroy the input feature and get a new one
    inFeature = None
    inFeature = inLayer.GetNextFeature()


感谢您对@MikeT的见识。GDAL / OGR文档在其整个食谱中均使用“ Destroy()”方法。您认为该方法有哪些问题?
亚伦

1
在某些情况下,当您使用Destroy()时可能会发生段错误,并且在绑定中公开此方法是一个设计错误。更好的方法是取消引用GDAL对象,例如inFeature = None。GDAL / OGR食谱不属于GDAL / OGR核心团队,也不由GDAL / OGR核心团队编写。
Mike T

@MikeT我已经编辑了帖子,以包含您的评论-谢谢。
亚伦

31

有许多模块可以读取Python中的shapefile,其版本早于ArcPy,请查看Python包索引(PyPi):shapefile。GIS SE中也有很多示例(例如,搜索[Python] Fiona

所有人都可以读取几何图形,字段和投影。

但是其他模块(例如PySAL):Python空间分析库Cartopy(使用pyshp)或Matplotlib Basemap也可以读取shapefile等。

最容易使用的是Fiona,但是如果您只知道ArcPy,请使用pyshp,因为osgeoFiona要求安装GDAL C / C ++库,因此GeoPandas需要Pandas模块,而PySAL太大(很多其他方法)

如果您只想读取shapefile的内容,则不需要复杂的事情,只需使用也在ArcPy中实现的地理接口协议(GeoJSON)(ArcPy:AsShape

使用Fiona(作为Python词典):

import fiona
with fiona.open('a_shape.shp') as shp:
     # schema of the shapefile
     print shp.schema
     {'geometry': 'Point', 'properties': OrderedDict([(u'DIP', 'int:2'), (u'DIP_DIR', 'int:3'), (u'TYPE', 'str:10')])}
     # projection
     print shp.crs
     {u'lon_0': 4.367486666666666, u'ellps': u'intl', u'y_0': 5400088.438, u'no_defs': True, u'proj': u'lcc', u'x_0': 150000.013, u'units': u'm', u'lat_2': 49.8333339, u'lat_1': 51.16666723333333, u'lat_0': 90}
     for feature in shp:
        print feature              
{'geometry': {'type': 'Point', 'coordinates': (272070.600041, 155389.38792)}, 'type': 'Feature', 'id': '0', 'properties': OrderedDict([(u'DIP', 30), (u'DIP_DIR', 130), (u'TYPE', u'incl')])}
{'geometry': {'type': 'Point', 'coordinates': (271066.032148, 154475.631377)}, 'type': 'Feature', 'id': '1', 'properties': OrderedDict([(u'DIP', 55), (u'DIP_DIR', 145), (u'TYPE', u'incl')])}
{'geometry': {'type': 'Point', 'coordinates': (273481.498868, 153923.492988)}, 'type': 'Feature', 'id': '2', 'properties': OrderedDict([(u'DIP', 40), (u'DIP_DIR', 155), (u'TYPE', u'incl')])}

使用pyshp(作为Python词典)

import shapefile
reader= shapefile.Reader("a_shape.shp")
# schema of the shapefile
print dict((d[0],d[1:]) for d in reader.fields[1:])
{'DIP_DIR': ['N', 3, 0], 'DIP': ['N', 2, 0], 'TYPE': ['C', 10, 0]}
fields = [field[0] for field in reader.fields[1:]]
for feature in reader.shapeRecords():
    geom = feature.shape.__geo_interface__
    atr = dict(zip(fields, feature.record))
    print geom, atr
{'type': 'Point', 'coordinates': (272070.600041, 155389.38792)} {'DIP_DIR': 130, 'DIP': 30, 'TYPE': 'incl'}
{'type': 'Point', 'coordinates': (271066.032148, 154475.631377)} {'DIP_DIR': 145, 'DIP': 55, 'TYPE': 'incl'}
{'type': 'Point', 'coordinates': (273481.498868, 153923.492988)} {'DIP_DIR': 155, 'DIP': 40, 'TYPE': 'incl'}

使用osgeo / ogr(作为Python词典)

from osgeo import ogr
reader = ogr.Open("a_shape.shp")
layer = reader.GetLayer(0)
for i in range(layer.GetFeatureCount()):
    feature = layer.GetFeature(i)
    print feature.ExportToJson()
{"geometry": {"type": "Point", "coordinates": [272070.60004, 155389.38792]}, "type": "Feature", "properties": {"DIP_DIR": 130, "DIP": 30, "TYPE": "incl"}, "id": 0}
{"geometry": {"type": "Point", "coordinates": [271066.032148, 154475.631377]}, "type": "Feature", "properties": {"DIP_DIR": 145, "DIP": 55, "TYPE": "incl"}, "id": 1}
{"geometry": {"type": "Point", "coordinates": [273481.49887, 153923.492988]}, "type": "Feature", "properties": {"DIP_DIR": 155, "DIP": 40, "TYPE": "incl"}, "id": 2}

使用GeoPandas(作为Pandas数据框)

import geopandas as gp
shp = gp.GeoDataFrame.from_file('a_shape.shp')
print shp
        DIP_DIR    DIP  TYPE                       geometry
0         130       30  incl          POINT (272070.600041 155389.38792)
1         145       55  incl          POINT (271066.032148 154475.631377)
2         155       40  incl          POINT (273481.498868 153923.492988)

*关于geopandas的注意事项您必须使用较早版本的Fiona和GDAL,否则它将无法安装。GDAL:1.11.2 Fiona:1.6.0 Geopandas:0.1.0.dev-

网络上甚至有许多教程,甚至还有书籍(Python地理空间开发使用Python学习地理空间分析和使用Python进行地理处理,正在印刷中)

更一般而言,如果您想在没有ArcPy的情况下使用Python,请查看使用Python对shapefile进行简单主题映射?


请注意,菲奥娜(Fiona)的首页上写着The kinds of data in GIS are roughly divided into rasters representing continuous scalar fields (land surface temperature or elevation, for example) and vectors representing discrete entities like roads and administrative boundaries. Fiona is concerned exclusively with the latter
Mawg

2
显然,问题是关于shapefile而不是栅格。它们是栅格文件的其他模块。
基因

好答案!2017年有什么更新吗?
迈克尔(Michael)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.