>>> from env_helper import info; info()
页面更新时间: 2024-07-23 22:21:25
运行环境:
Linux发行版本: Debian GNU/Linux 12 (bookworm)
操作系统内核: Linux-6.1.0-23-amd64-x86_64-with-glibc2.36
Python版本: 3.11.2
5.4. 高级主题¶
5.4.1. 切片和masking迭代器¶
若想添加空间矢量数据格式,可查找外包四边形(bounding box) 。 函数
fiona.collection.Collection.items
返回一个FIDs迭代器,
并记录交叉指定的 (minx, miny, maxx, maxy)
bounding box或几何对象。
自己的坐标参考系统可用来解译box值。 如果要查看迭代器列表,可通过 Python
的内置 list()
函数 ,如下所示。
>>> import fiona
>>> c = fiona.open('/gdata/prov_capital.shp')
>>> hits = list(c.items(bbox=(-5.0, 55.0, 0.0, 60.0)))
>>> len(hits)
0
迭代器与切割参数itertools.islice
的 stop
或
start, stop[, step]
的功能相同。要想查找迭代器的前两个参数,暂停即可。
>>> hits = c.items(2, bbox=(-5.0, 55.0, 0.0, 60.0))
>>> len(list(hits))
0
要想得到迭代器第三到第五个参数,启动和停止即可。
>>> hits = c.items(2, 5, bbox=(-5.0, 55.0, 0.0, 60.0))
>>> len(list(hits))
0
要想过滤属性值,可使用Python的内置 :py:func:filter
和:py:keyword:lambda
函数
,或者你也可以用单一属性的过滤功能,返回值为 True
or False
。
>>> def pass_positive_area(rec):
>>> return rec['properties'].get('AREA', 0.0)>0.0
>>> c = fiona.open('/gdata/prov_capital.shp')
>>> hits = filter(pass_positive_area, c)
>>> len(list(hits))
0
5.4.2. 多层数据的处理¶
读取多层数据¶
一般GIS数据格式可以在单个文件或库中编码多个层或特征类型,而ESRI
Shapefile只有一个主题层或功能型的单一dataset。ESRI文件地理数据库
<http://www.gdal.org/ogr/drv_filegdb.html>
就是一个例子,它是一个包含多个shapefiles的库。以下命令是Fiona测试数据中创建的二层数据源。
>>> import subprocess
>>> import os
>>> if not os.path.exists('/tmp/data'):
>>> os.mkdir('/tmp/data')
>>>
>>> cmd1 = 'ogr2ogr /tmp/data/ /gdata/GSHHS_c.shp GSHHS_c -nln foo'
>>> cmd2 = 'ogr2ogr /tmp/data/ /gdata/GSHHS_c.shp GSHHS_c -nln bar'
>>> subprocess.call(cmd1, shell=True)
>>> subprocess.call(cmd2, shell=True)
Warning 1: Value 50654050.6944999993 of field area of feature 0 not successfully written. Possibly due to too larger number with respect to field width
Warning 1: Value 50654050.6944999993 of field area of feature 1 not successfully written. Possibly due to too larger number with respect to field width
Warning 1: Value 29220969.7270000018 of field area of feature 2 not successfully written. Possibly due to too larger number with respect to field width
Warning 1: Value 20154740.0899999999 of field area of feature 3 not successfully written. Possibly due to too larger number with respect to field width
Warning 1: Value 17534164.0667999983 of field area of feature 4 not successfully written. Possibly due to too larger number with respect to field width
Warning 1: Value 13919140.5654000007 of field area of feature 1736 not successfully written. Possibly due to too larger number with respect to field width
Warning 1: Value 50654050.6944999993 of field area of feature 0 not successfully written. Possibly due to too larger number with respect to field width
Warning 1: Value 50654050.6944999993 of field area of feature 1 not successfully written. Possibly due to too larger number with respect to field width
Warning 1: Value 29220969.7270000018 of field area of feature 2 not successfully written. Possibly due to too larger number with respect to field width
Warning 1: Value 20154740.0899999999 of field area of feature 3 not successfully written. Possibly due to too larger number with respect to field width
Warning 1: Value 17534164.0667999983 of field area of feature 4 not successfully written. Possibly due to too larger number with respect to field width
Warning 1: Value 13919140.5654000007 of field area of feature 1736 not successfully written. Possibly due to too larger number with respect to field width
0
一个数据源层可以用函数fiona.listlayers
列一下,写法是
listlayers()
。在
Shapefile格式的情况下,层的名称需匹配文件库的名称。
>>> import fiona
>>> fiona.listlayers('/gdata')
['GSHHS_h',
'hyd2_4l',
'shape_towns',
'county_popu',
'GSHHS_c',
'prov_capital',
'world_pt',
'region_popu',
'world_spatial_filter',
'region_popu2',
'spatial_filter',
'GSHHS_l_L1']
不像OGR,Fiona没有层与数据源的分类。要想访问层,需用数据源路径打开一个集,并用
layer
来指定该层。
>>> import pprint
>>> datasrc_path = '/gdata'
>>> for name in fiona.listlayers(datasrc_path):
>>> with fiona.open(datasrc_path, layer=name) as c:
>>> pprint.pprint(c.schema)
{'geometry': 'Polygon',
'properties': OrderedDict([('id', 'str:80'),
('level', 'int:10'),
('source', 'str:80'),
('parent_id', 'int:10'),
('sibling_id', 'int:10'),
('area', 'float:19.11'),
('Shape_Leng', 'float:19.11'),
('Shape_Area', 'float:19.11')])}
{'geometry': 'LineString',
'properties': OrderedDict([('FNODE_', 'int:11'),
('TNODE_', 'int:11'),
('LPOLY_', 'int:11'),
('RPOLY_', 'int:11'),
('LENGTH', 'float:12.3'),
('HYD2_4M_', 'int:11'),
('HYD2_4M_ID', 'int:11'),
('GBCODE', 'int:6'),
('NAME', 'str:60'),
('LEVEL_RIVE', 'int:1'),
('LEVEL_LAKE', 'int:1')])}
{'geometry': 'Point',
'properties': OrderedDict([('PK_UID', 'int:4'),
('Name', 'str:62'),
('Peoples', 'int:7'),
('LocalCounc', 'int:1'),
('County', 'int:1'),
('Region', 'int:1')])}
{'geometry': 'Polygon',
'properties': OrderedDict([('PAC', 'int:10'),
('NAME', 'str:60'),
('POPU', 'float:13.11'),
('AREA', 'float:13.11'),
('Shape_Leng', 'float:19.11'),
('Shape_Area', 'float:19.11')])}
{'geometry': 'Polygon',
'properties': OrderedDict([('id', 'str:80'),
('level', 'int:10'),
('source', 'str:80'),
('parent_id', 'int:10'),
('sibling_id', 'int:10'),
('area', 'float:19.11'),
('Shape_Leng', 'float:19.11'),
('Shape_Area', 'float:19.11')])}
{'geometry': 'Point',
'properties': OrderedDict([('name', 'str:100'),
('lat', 'float:13.11'),
('lon', 'float:13.11')])}
{'geometry': 'Point',
'properties': OrderedDict([('CAT', 'int:16'),
('FIPS_CNTRY', 'str:80'),
('CNTRY_NAME', 'str:80'),
('AREA', 'float:17.2'),
('POP_CNTRY', 'float:17.2'),
('ORIG_FID', 'int:10')])}
{'geometry': 'Polygon',
'properties': OrderedDict([('code4', 'int:5'),
('name', 'str:50'),
('code2', 'int:5'),
('pname', 'str:50'),
('popu', 'float:13.11')])}
{'geometry': 'Polygon',
'properties': OrderedDict([('id', 'str:80'),
('level', 'int:10'),
('source', 'str:80'),
('parent_id', 'int:10'),
('sibling_id', 'int:10'),
('area', 'float:19.11'),
('Shape_Leng', 'float:19.11'),
('Shape_Area', 'float:19.11')])}
{'geometry': 'Polygon',
'properties': OrderedDict([('code4', 'int:5'),
('name', 'str:50'),
('code2', 'int:5'),
('pname', 'str:50'),
('popu', 'float:13.11')])}
{'geometry': 'Polygon', 'properties': OrderedDict([('FID', 'int:11')])}
{'geometry': 'Polygon',
'properties': OrderedDict([('id', 'str:80'),
('level', 'int:10'),
('source', 'str:80'),
('parent_id', 'int:10'),
('sibling_id', 'int:10'),
('area', 'float:24.15')])}
层还可以由索引来指定。
>>> for i, name in enumerate(fiona.listlayers(datasrc_path)):
>>> with fiona.open(datasrc_path, layer=i) as c:
>>> print(len(c))
153113
2143
8101
2908
1765
34
3784
349
2466
349
1
5707
若没有指定层, fiona.open
会返回第一层的开放集 。
>>> with fiona.open(datasrc_path) as c:
>>> c.name == fiona.listlayers(datasrc_path)[0]
要打开一个只读的shapefile,最简单的方法就是 fiona.open
函数,可以把其文件名作为一个命名图层的数据源。 如:
fiona.open('/tmp/foo.shp', 'r', layer='foo')
在实践中,依靠隐含的第一层和默认 'r'
模式是很实用的。
写入多层数据¶
要写一个全新的多层源数据,只需提供唯一的名字到 layer
参数中即可。
>>> 'wah' not in fiona.listlayers(datasrc_path)
True
>>> datasrc_path = '/tmp/data'
>>> with fiona.open(datasrc_path, layer='bar') as c:
>>> with fiona.open(datasrc_path, 'w', layer='wah', **c.meta) as d:
>>> d.write(next(iter(c)))
>>> fiona.listlayers(datasrc_path)
['bar', 'wah', 'foo']
在 'w'
模式中,如果指定的话,会覆盖原有的层,就像是Python的open
功能似的。
>>> 'wah' in fiona.listlayers(datasrc_path)
True
>>> with fiona.open(datasrc_path, layer='bar') as c:
>>> with fiona.open(datasrc_path, 'w', layer='wah', **c.meta) as d:
>>> pass