Monday, 4 May 2015

python - Adding column to shapefile with Fiona?


I wrote the script to copy a existing shapefile tc_line to a new file tc_pi, and it ran fine:


from shapely.geometry import mapping, shape

import fiona

with fiona.open('tc_line.shp', 'r') as input:
schema = input.schema.copy()
input_crs = input.crs
with fiona.open('tc_pi.shp', 'w', 'ESRI Shapefile', schema, input_crs) as output:
for elem in input:
output.write({'properties':elem['properties'],'geometry': mapping(shape(elem['geometry']))})

Now I want to copy the existing file and add a new column (type: float) containing "1" to the attribute table (I would like the new-added column to be attached to the right of the existing columns in the attribute talle), so I edited the code above to this:



from shapely.geometry import mapping, shape
import fiona

with fiona.open('tc_line.shp', 'r') as input:
schema = input.schema.copy()
input_crs = input.crs
schema['properties']['pi'] = 'float'
with fiona.open('tc_pi.shp', 'w', 'ESRI Shapefile', schema, input_crs) as output:
for elem in input:
output.write({'properties':elem['properties'],'geometry': mapping(shape(elem['geometry']))})


but error occurred:


Traceback (most recent call last):


File "C:\Users\Heinz\Desktop\test.py", line 10, in
output.write({'properties':elem['properties'],'geometry': mapping(shape(elem['geometry']))})
File "C:\Python27\lib\site-packages\fiona\collection.py", line 333, in write
self.writerecords([record])
File "C:\Python27\lib\site-packages\fiona\collection.py", line 327, in writerecords

self.session.writerecs(records, self)
File "fiona/ogrext.pyx", line 1024, in fiona.ogrext.WritingSession.writerecs (fiona/ogrext.c:17361)
ValueError: Record does not match collection schema: [u'cat_', u'value', u'label'] != ['pi', u'label', u'value', u'cat_']

How to solve this and achieve my objective of 'copy the existing file and add a new column (type: float) containing "1" to the attribute table of new file'?


I am working with python 2.7.12, Fiona 1.7.0



Answer



It seems to me that you have some problems with Fiona. Remember that all the elements are dictionaries


1) you define a new field schema['properties']['pi'] = 'float'
2) this field must be in in the properties of every elements



with fiona.open('tc_line.shp', 'r') as input:
schema = input.schema.copy()
input_crs = input.crs
schema['properties']['pi'] = 'float'
with fiona.open('tc_pi.shp', 'w', 'ESRI Shapefile', schema, input_crs) as output:
for elem in input:
elem['properties']['pi']= 1
output.write({'properties':elem['properties'],'geometry': mapping(shape(elem['geometry']))})

If you're not comfortable with Python dictionaries, use GeoPandas (it uses Fiona)



import geopandas as gpd
gdf = gpd.read_file("tc_line.shp")
gdf["pi"]= 1
gdf.to_file("tc_pi.shp")

No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...